在以下代码中:
std::atomic<int> myint; //Shared variable
//(...)
if( --myint == 0) {
//Code block B
}
是否有多个线程可以访问名为“Code Block B”的块?
请考虑溢出不会发生,'if'由多个线程同时执行,整个程序中对 myint 的唯一修改是 - if和 myint 中的myint 初始化为正值。
答案 0 :(得分:18)
C ++ 0x paper N2427(atomics)大致说明如下。我稍微改变了措辞,因此更容易阅读特定的减量情况,我更改的部分是粗体:
效果: 以原子方式替换对象中的值,并将减量的结果应用于对象中的值 和给定的操作数。内存受订单影响。这些操作是在[由N2334或后继者添加的新部分]中的“与...同步”定义的意义上的读 - 修改 - 写操作,因此这样的操作和产生输入值的评估与任何评估同步。读取更新的值。
返回: 原子地,对象的值紧接在减量之前。
原子操作保证递减运算符将返回变量在操作之前保存的值,这是原子的,因此另一个线程的更新中没有中间值。
这意味着以下是这个代码的唯一可能执行的2个线程:
(Initial Value: 1)
Thread 1: Decrement
Thread 1: Compare, value is 0, enter region of interest
Thread 2: Decrement
Thread 2: Compare, value is -1, don't enter region
或
(Initial Value: 1)
Thread 1: Decrement
Thread 2: Decrement
Thread 1: Compare, value is 0, enter region of interest
Thread 2: Compare, value is -1, don't enter region
案例1是无趣的预期案例。
情况2交织递减操作并稍后执行比较操作。因为递减和取指操作是 atomic ,所以线程1不可能接收0以外的值进行比较。 不能接收-1,因为操作是原子的......读取发生在递减时,不是在比较时发生。更多线程不会改变这种行为。
答案 1 :(得分:1)
代码块始终执行并不明显。如果运算符“ - ”以这样的方式实现,即它将旧值存储在其返回值中并在单个原子指令中递减(我非常确定x86具有这样的指令),那么是的,它应该像一个多线程的互斥块。我不确定默认情况下它是如何工作的,但答案可能在于新的标准文档:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html
答案 2 :(得分:-1)
根据您的约束条件,不可能有多个线程进入块。但是也没有保证任何线程进入这个块:
thread A: decrement myint to 0
thread B: decrement myint to -1
thread A: compare to 0 -> false -> don't enter (and neither anyone else)
如果这是一个问题(我假设),那么此代码将无效(至少不是始终)。