原子布尔变量的一条语句中的多重赋值
Posted
技术标签:
【中文标题】原子布尔变量的一条语句中的多重赋值【英文标题】:Multiple assignment in one statement for atomic bool variables 【发布时间】:2017-10-09 22:14:17 【问题描述】:从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
之前将b
设置为true
,以将其值分配给a
,所以在指令结束时a
的值是true
?
(这也意味着后一个版本似乎效率较低)
【问题讨论】:
很难说没有看到实际的编译器输出,但std::atomic::operator=()
应该返回传递给它的值,所以我认为a = ...
不会实际读取@ 的值987654335@,它只会从operator=
的输出中接收false
。现在,在多线程情况下,当reset()
退出时,b
仍然可能是true
,但这是另一回事。
@RemyLebeau 好吧,那几乎可以回答我的问题,应该没有任何区别,否则编译器将是次优的。谢谢! (当然,reset
的末尾可能是 b
是 true
如果另一个线程干预)
【参考方案1】:
是的,有区别
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.
因此,第二个线程以 reverse 存储顺序 (a = b = false;
) 执行原子加载 (bool a_observed = a.load(); bool b_observed = b.load();
) 可能会以以下三种方式之一观察变化:
b
和 a
的旧值
加载a
,加载b
,b
a
b
的新值和a
的旧值
存储b
,加载a
,a
b
存储b
,加载a
,加载b
,a
a
,存储b
,a
b
加载a
,存储b
,加载b
,a
b
和 a
的新值
存储b
,存储a
,加载a
,加载b
相比之下,memory_order_seq_cst
用于在a
之前存储b
而(在另一个线程中)在b
之前加载a
保证永远不会观察到以下内容:
a
的新值和b
的旧值
【讨论】:
谢谢,我已经为 Clang 3.8 测试了 here【参考方案2】:Godbolt link
两者之间的差异很小。唯一真正的区别是分配顺序被颠倒了。如果开启优化,则无法区分。
【讨论】:
非常酷的链接和网站!实际上,当使用更复杂的定义时,不同之处在于即使优化后也会保留顺序godbolt.org/g/kozyTp以上是关于原子布尔变量的一条语句中的多重赋值的主要内容,如果未能解决你的问题,请参考以下文章