在原子布尔变量的一个语句中多次赋值
继Multiple assignment in one line后,我很想知道这对原子数据类型是如何工作的,特别是对于布尔类型的例子。在原子布尔变量的一个语句中多次赋值
考虑:
class foo {
std::atomic<bool> a;
std::atomic<bool> b;
public:
void reset();
[...] //Other methods that might change a and b
}
是否有任何区别:
void foo::reset() {
a = false;
b = false;
}
和:
void foo::reset() {
a = b = false;
}
也就是说,在第二种情况下,可以在发生b
分配后false
,另一个线程集b
到true
在读取b
之前将其值分配给a
,以便在指令结束时a
的值为true
?
(这也意味着后者的版本似乎是低效率)
是的,有
a = false;
b = false;
和
a = b = false;
如果a
和b
是原子之间的差。由于分配从右到左进行,后者相当于
b = false;
a = false; // since atomic::operator= (from above) returns its argument
从第一个版本不同,因为a
和b
是原子和assignment is done仿佛std::atomic::store
被称为与存储顺序memory_order_seq_cst
。从而,存储器模型guarantees
a single total modification order of all atomic operations that are so tagged.
其结果是,第二线程在反向顺序存储(a = b = false;
)的可观察的以下三种方式一个的变化执行原子负载(bool a_observed = a.load(); bool b_observed = b.load();
) :两个b
和
- 旧值
a
- 负载
a
,负载b
,店,b
店a
为
- 负载
- 新价值
a
- 店
b
,负载a
,店,负载a
b
- 店面
b
,加载a
,负载b
,商店a
- 负载
a
,存储b
,商店,负载a
b
- 负载
a
,存储b
,负载b
,商店a
- 店
- 为新值
b
和a
- 商店
b
,存储a
,负载a
,负载b
- 商店
b
和旧值
相反,memory_order_seq_cst
为前b
保证前a
同时存储b
(在其他线程)装载a
该以下从未观察到:
-
为
- 新的价值和
b
a
谢谢,我已经测试过[这里](https:// godbolt .org/g/kozyTp)为Clang 3.8 – Antonio
有两者之间的差异很小。唯一真正的区别是分配顺序被翻转。如果打开优化,则无法区分。
非常酷的链接和网站!实际上,当使用更复杂的定义时,差别在于即使在优化时顺序也会保留https://godbolt.org/g/kozyTp – Antonio
硬盘没有看到实际的编译器输出的说旧值,但'的std ::原子::运算符=()'应该返回传递给它的价值,所以我认为'a = ...'根本不会读取'b'的值,它只会从'operator ='的输出中接收'false'。现在,在多线程情况下,当'reset()'退出时,'b'仍然可以是'true',但那是另一回事。 –
@RemyLebeau好吧,那么我的问题几乎可以回答,不应该有任何区别,否则编译器会是次优的。谢谢! (当然,在'reset'结束时,如果另一个线程干预,'b'可能是'true') – Antonio