Atomic operations in C ++

I have a set of C ++ functions:

funcB(){}; funcC(){}; funcA() { funcB(); funcC(); } 

Now I want to make funcA atomic, i.e. funcB and funcC calls inside funcA must be performed atomically. Is there any way to achieve this?

+6
source share
3 answers

One way to achieve this is to use the new (C ++ 11) functions std::mutex and std::lock_guard .

For each protected resource, an instance of one global std::mutex ; each thread then blocks this mutex, as required, by creating std::lock_guard :

 #include <thread> #include <iostream> #include <mutex> #include <vector> // A single mutex, shared by all threads. It is initialized // into the "unlocked" state std::mutex m; void funcB() { std::cout << "Hello "; } void funcC() { std::cout << "World." << std::endl; } void funcA(int i) { // The creation of lock_guard locks the mutex // for the lifetime of the lock_guard std::lock_guard<std::mutex> l(m); // Now only a single thread can run this code std::cout << i << ": "; funcB(); funcC(); // As we exit this scope, the lock_guard is destroyed, // the mutex is unlocked, and another thread is allowed to run } int main () { std::vector<std::thread> vt; // Create and launch a bunch of threads for(int i =0; i < 10; i++) vt.push_back(std::thread(funcA, i)); // Wait for all of them to complete for(auto& t : vt) t.join(); } 

Notes:

  • In your example, non- funcA related funcA can call either funcB or funcC without observing the lock set by funcA .
  • Depending on the structure of your program, you can manage the mutex's lifetime differently. For example, it may be a member of a class class that includes funcA .
+11
source

In general, NO. Atomic operations are very precisely defined. What you want is a semaphore or mutex.

+6
source

If you are using GCC 4.7, you can use the new Transactional Memory function to do the following:

Transactional memory is designed to simplify programming with threads, in particular, to synchronize access to data shared by multiple threads using transactions. As with the databases, a transaction is a unit of work that either completes completely or has no effect at all (i.e., transactions are performed atomically). In addition, transactions are isolated from each other, so that each transaction sees a consistent view of memory.

Currently, transactions are only supported in C ++ and C in the form of transaction statements, transaction expressions, and function transactions. In the following example, both a and b will be read, and the difference will be written to c, all atomically and isolated from other transactions:

 __transaction_atomic { c = a - b; } 

Therefore, another thread may use the following code to update b simultaneously, without forcing c to hold a negative value (and without the need to use other synchronization constructs, such as locks or C ++ 11 atoms):

 __transaction_atomic { if (a > b) b++; } 

The exact semantics of transactions are defined in terms of the C ++ 11 / C1X memory model (see the specification link below). Roughly speaking, transactions provide synchronization guarantees similar to those that would be guaranteed if a single global lock were used as protection for all transactions. Please note that, like other synchronization constructs in C / C ++, transactions rely on a program without taking into account the distribution (for example, writing without a transaction, which simultaneously with transactional reading to the same memory location, is a data consumption).

Additional information: http://gcc.gnu.org/wiki/TransactionalMemory

+1
source

Source: https://habr.com/ru/post/911011/


All Articles