C ++ 11 when incrementing an atomic variable and assigning it to another value, is this an atomic operation?

I got confused in atom work in C ++ 11,

I know that the atomic variable self increment is atomic,

but I use assignment for a different meaning, just doubt it.

the code is the same:

//.... static std::atomic<int> i; // global variable //.... // in the thread int id = ++i; 

when using destination in different threads is unique id value?

test code:

 #include <thread> #include <mutex> #include <atomic> #include <iostream> class A { public: static int idGenerator; static std::mutex m; A () { // i know this operation will keep the id_ is unique std::lock_guard<std::mutex> lock(m); id_ = ++idGenerator; } void F(std::string name) { std::cout << name << " " << id_ << std::endl; } private: int id_; }; int A::idGenerator = 0; std::mutex A::m; class B { public: static int idGenerator; B () { // after self increment, is the assignment atomic? id_ = (++idGenerator); } void F(std::string name) { std::cout << name << " " << id_.load() << std::endl; } private: std::atomic<int> id_; }; int B::idGenerator = 0; void funcA() { A a2; a2.F("a2"); } void funcB() { B b2; b2.F("b2"); } int main() { A a1; B b1; std::thread t1(&funcA); std::thread t2(&funcB); a1.F("a1"); b1.F("b1"); t1.join(); t2.join(); return 0; } 

there are three threads

The use lock_guard class is unique.

Class B just uses an atomic operation and assigns to a variable

+6
source share
3 answers

The specification of atomic increment functions gives a critical understanding of their behavior - from http://en.cppreference.com/w/cpp/atomic/atomic/operator_arith for Integral T types:

 T operator++(); T operator++() volatile; T operator++( int ); T operator++( int ) volatile; 

Note that they return the value of T by value and never return the usual T& from pre-increment. For this reason, “reading” a post-increment value is not a second separate operation and is part of the atomic increment operation itself.

See also the text “Return Value” and “Note” on the page above.

+7
source
 static std::atomic<int> i; // global variable // in the thread int id = ++i; 

when using destination in different threads is unique id value?

Yes. C ++ atomic variables ensure that ++i will be evaluated atomically, so each id value for different threads is unique.

Expression id = ++i; performed by the next step.

  • atomically increment i , and the subexpression ( ++i ) is evaluated after the incremental value.
  • assign the "estimated value" id . (this step is not atomic)
+2
source

kaka_ace,

Unfortunately, in case you provided, it is not atomic.

Here's the reason the pre-increment operation is atomic, look at the generated assembly:

  add %l0,1,%l0 

(may vary slightly depending on the assembly used)

But this. 1. That is why it is atomic.

When you assign a pre-increment to a local variable, these are at least two commands:

 add %l0,1,%l0 st l0, [%fp-4] 

This generates at least two commands and, therefore, is no longer atomic.

Please let me know if you have any questions!

0
source

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


All Articles