[英]C++11 when increment the atomic variable, and assign it to other value, is it atomic operation?
i'm confused about the atomic operation on c++11, 我对c ++ 11上的原子操作感到困惑,
i know the atomic variable self increment is atomic operation, 我知道原子变量自增量是原子操作,
but i use the assignment to other value, just doubt it. 但我使用赋值给其他值,只是怀疑它。
the code just like: 代码就像:
//....
static std::atomic<int> i; // global variable
//....
// in the thread
int id = ++i;
when using the assignment at different threads, is the id unique value? 在不同线程使用赋值时,id是唯一值吗?
the 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, 有三个线程,
A class use lock_guard keep unique. 一个类使用lock_guard保持唯一。
B class just use atomic operation, and assign to the variable B类只使用原子操作,并赋值给变量
The specification of the atomic increment functions give a crucial insight into their behaviour - from http://en.cppreference.com/w/cpp/atomic/atomic/operator_arith for Integral T
types: 原子增量函数的规范提供了对其行为的重要见解 - 来自http://en.cppreference.com/w/cpp/atomic/atomic/operator_arith的Integral
T
类型:
T operator++();
T operator++() volatile;
T operator++( int );
T operator++( int ) volatile;
Notice they return a T
by value, and never return the usual T&
from a pre-increment. 注意它们返回一个
T
值,并且永远不会从预增量返回通常的T&
。 For that reason, the "read" of post-incremented value is not a second distinct operation, and is part of the atomic increment operation itself. 出于这个原因,后递增值的“读取”不是第二个不同的操作,并且是原子增量操作本身的一部分。
See also the "Return Value" and "Note" text on the above-linked page. 另请参见上述链接页面上的“返回值”和“注释”文本。
static std::atomic<int> i; // global variable
// in the thread
int id = ++i;
when using the assignment at different threads, is the id unique value?
在不同线程使用赋值时,id是唯一值吗?
Yes. 是。 C++ atomic variables ensure that
++i
will be evaluated atomically, so each values of id
on different threads are unique. C ++原子变量确保
++i
将以原子方式进行求值,因此不同线程上id
每个值都是唯一的。
The expression id = ++i;
表达式
id = ++i;
is executed following steps. 按照以下步骤执行。
i
, and sub-expression( ++i
) is evaluated post-increment value. i
,并且子表达式( ++i
)在递增后的值处被评估。 id
. id
。 (this step is non-atomically) kaka_ace, kaka_ace,
Unfortunately in the case you provided, it isn't atomic. 不幸的是,在您提供的情况下,它不是原子的。
Here's the reason why the pre-increment operation is atomic, look at the assembly generated: 这就是为什么预增量操作是原子的,看看生成的程序集:
add %l0,1,%l0
(might vary a little bit depending on the assembly used) (可能会有所不同,具体取决于使用的组件)
But that's it. 但就是这样。 1 operation.
1次操作。 That's why it's atomic.
这就是为什么它是原子的。
When you're assigning a pre-increment to a local variable, that's at least two instructions: 当您为局部变量分配预增量时,至少有两条指令:
add %l0,1,%l0
st l0, [%fp-4]
That generates at least two instructions, and hence is no longer atomic. 这会产生至少两条指令,因此不再是原子的。
Please let me know if you have any questions! 请让我知道,如果你有任何问题!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.