kak*_*ace 6 c++ multithreading mutex atomic c++11
我对c ++ 11上的原子操作感到困惑,
我知道原子变量自增量是原子操作,
但我使用赋值给其他值,只是怀疑它.
代码就像:
//....
static std::atomic<int> i; // global variable
//....
// in the thread
int id = ++i;
Run Code Online (Sandbox Code Playgroud)
在不同线程使用赋值时,id是唯一值吗?
测试代码:
#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;
}
Run Code Online (Sandbox Code Playgroud)
有三个线程,
一个类使用lock_guard保持唯一.
B类只使用原子操作,并赋值给变量
原子增量函数的规范提供了对其行为的重要洞察 - 来自 http://en.cppreference.com/w/cpp/atomic/atomic/operator_arith的积分T类型:
T operator++();
T operator++() volatile;
T operator++( int );
T operator++( int ) volatile;
Run Code Online (Sandbox Code Playgroud)
注意它们返回一个Tby值,并且永远不会T&从pre-increment 返回通常值.出于这个原因,后递增值的"读取"不是第二个不同的操作,并且是原子增量操作本身的一部分.
另请参见上述链接页面上的"返回值"和"注释"文本.
static std::atomic<int> i; // global variable
// in the thread
int id = ++i;
Run Code Online (Sandbox Code Playgroud)
在不同线程中使用赋值时,id 是唯一值吗?
是的。C++ 原子变量确保++i将被原子地评估,因此id不同线程上的每个值都是唯一的。
该表达式按id = ++i;以下步骤执行。
i,并且 sub-expression( ++i) 在递增后的值上求值。id. (这一步是非原子的)卡卡_ace,
不幸的是,在您提供的情况下,它不是原子的。
这里就是为什么预自增操作是原子的,看一下生成的程序集:
add %l0,1,%l0
Run Code Online (Sandbox Code Playgroud)
(根据所使用的组件可能会略有不同)
但仅此而已。1 操作。这就是为什么它是原子的。
当您将预增量分配给局部变量时,至少有两条指令:
add %l0,1,%l0
st l0, [%fp-4]
Run Code Online (Sandbox Code Playgroud)
这会生成至少两条指令,因此不再是原子的。
请让我知道,如果你有任何问题!