![](/img/trans.png)
[英]In C11/C++11, possible to mix atomic/non-atomic ops on the same memory?
[英]C++11 Atomic memory order with non-atomic variables
我不确定c ++ 11中的原子变量的内存排序保证如何影响对其他内存的操作。
假设我有一个线程周期性地调用write函数来更新一个值,另一个线程调用read来获取当前值。 是否保证d = value;
的影响d = value;
在a = version;
效果之前不会被看到a = version;
,并且会在b = version;
的影响之前看到b = version;
?
atomic<int> a {0};
atomic<int> b {0};
double d;
void write(int version, double value) {
a = version;
d = value;
b = version;
}
double read() {
int x,y;
double ret;
do {
x = b;
ret = d;
y = a;
} while (x != y);
return ret;
}
您的对象d
由两个线程写入和读取,并且它不是原子的。 这是不安全的,如多线程的C ++标准所示:
1.10 / 4如果其中一个修改了内存位置而另一个访问或修改了相同的内存位置,则两个表达式评估会发生冲突。
1.10 / 21程序的执行包含数据竞争,如果它在不同的线程中包含两个冲突的动作,其中至少有一个不是原子的,并且都不会发生在另一个之前。 任何此类数据争用都会导致未定义的行为。
重要编辑:
在非原子的情况下,你无法保证阅读和写作之间的顺序。 您甚至不能保证读者会读取作者写的值(这篇简短的文章解释了非原子变量的风险 )。
然而 ,读者的循环基于对周围原子变量的测试而完成,对此有很强的保证。 假设version
从不在编写者不同的调用之间重复,并且给出了获取其值的相反顺序:
d
写相比, d
读的顺序不可能是不幸的。 这意味着如果你的非原子的不利竞争条件,由于循环,你将最终读取最后一个value
。
规则是,给定一个执行一次的write
线程,没有其他任何修改a
, b
或d
,
a
和b
b
并查看存储在其中的version
,那么
d
; 和 value
。 注意第二部分是否为真取决于内存排序; 它与默认值( memory_order_seq_cst
)一样。
是否保证
d = value;
的影响d = value;
在a = version;
效果之前不会被看到a = version;
,并且会在b = version;
的影响之前看到b = version;
?
是的。 这是因为在读取或写入atomic<>
变量时隐含了顺序一致性障碍 。
不是在修改值之前和之后将version
标记存储到两个原子变量中,而是可以在修改之前和之后增加单个原子变量:
atomic<int> a = {0};
double d;
void write(double value)
{
a = a + 1; // 'a' become odd
d = value; //or other modification of protected value(s)
a = a + 1; // 'a' become even, but not equal to the one before modification
}
double read(void)
{
int x;
double ret;
do
{
x = a;
ret = value; // or other action with protected value(s)
} while((x & 2) || (x != a));
return ret;
}
这在Linux内核中称为seqlock : http : //en.wikipedia.org/wiki/Seqlock
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.