C++ 标准::原子<;int>;减量与比较

C++ 标准::原子<;int>;减量与比较,c++,multithreading,concurrency,c++11,atomicity,C++,Multithreading,Concurrency,C++11,Atomicity,关于以下代码: std::原子myint//共享变量 //(...) 如果(--myint==0){ //代码块B } 是否可能有多个线程访问名为“代码块B”的块I 请考虑溢出不会发生,即“if”是由多个线程同时执行的,在整个程序中对Myt的唯一修改是IF内的MyIt,MyIt用正值初始化。 < P>不可能不止一个线程进入块,考虑到你的限制。但也不能保证任何线程都会进入此块: thread A: decrement myint to 0 thread B: decrement myint t

关于以下代码:

std::原子myint//共享变量
//(...)
如果(--myint==0){
//代码块B
}
是否可能有多个线程访问名为“代码块B”的块I


请考虑溢出不会发生,即“if”是由多个线程同时执行的,在整个程序中对Myt的唯一修改是IF内的MyIt,MyIt用正值初始化。

< P>不可能不止一个线程进入块,考虑到你的限制。但也不能保证任何线程都会进入此块:

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)

如果这是一个问题(我假设),那么这段代码将无法工作(至少不总是)。

代码块是否总是执行并不明显。如果运算符“-”的实现方式是将旧值存储在返回值中,并在单个原子指令中递减(我很确定x86中有这样的指令),那么它应该像多线程的互斥块一样工作。我不确定默认情况下它是如何工作的,但答案可能在于新的标准文档:

C++0x论文(原子学)大致陈述了以下内容。我稍微更改了措辞,以便更容易阅读具体的减量情况,我更改的部分为粗体:

影响: 以原子方式将对象中的值替换为应用于对象中的值和给定操作数的减量的结果。内存受订单影响。这些操作是[由N2334或后续版本添加的新部分]中“与同步”定义意义上的读-修改-写操作,因此,此类操作和生成输入值的计算都与读取更新值的任何计算同步

返回: 原子上,紧靠减量之前的对象值

原子操作保证减量运算符将返回变量在操作前立即保存的值,这是原子操作,因此不会有来自另一个线程更新的中间值

这意味着只有以下两个线程可以执行此代码:

(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

案例1是无趣的预期案例


情况2交错递减操作,并在以后执行比较操作。因为减量和提取操作是原子操作,所以线程1不可能接收0以外的值进行比较。它无法接收-1,因为操作是原子的。。。读取在递减时进行,而不是在比较时进行。更多线程将不会更改此行为。

@Patrick这将是未定义的行为。真正的问题是std::atomic::operator--是否以原子方式返回旧值。@cdleonard--减量是原子的,并返回结果。但是,当您将结果与零进行比较时,没有什么可以阻止另一个线程立即再次递增或递减该值。@BoPersson但是返回的值不会被myint的任何后续修改所修改。因此,理论上,如果myint的值是单调递减的(不考虑溢出),那么只有一个线程可以进入块。@curiousguy我不知道你在说什么,我从来没有在我的问题上说过“下溢”…=)那么,如果我有:线程A:递减到1,线程B:递减到0,线程A:比较到0真,线程B:比较到0真。@AndréPuel啊,我想你明白我的意思了(还有你的答案)。@AndréPuel这是不可能的,--运算符执行递减并获取一条指令,因此,即使按照您在注释中指定的执行顺序,线程A中的值也将是1。@SoapBox这正是我要问的!运算符--standard是否定义减量和取数必须以原子方式进行?请注意,我检查了N3291,尽管它使用了不同的措辞,但它同意这一点。对于“-myint;if(myint==0){}”?@paulm,这仍然正确吗?如果减量并检入两个不同的语句,则绝对不正确。必须在同一声明中完成。
(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