[英]C++0x atomic implementation in c++98 question about __sync_synchronize()
[英]C++: __sync_synchronize() still needed with std::atomic?
我一直遇到不常见但又经常发生的比赛情况。 该程序有两个线程,并使用std :: atomic。 我将代码的关键部分简化为:
std::atomic<uint64_t> b; // flag, initialized to 0
uint64_t data[100]; // shared data, initialized to 0
线程1(发布):
// set various shared variables here, for example
data[5] = 10;
uint64_t a = b.exchange(1); // signal to thread 2 that data is ready
线程2(接收):
if (b.load() != 0) { // signal that data is ready
// read various shared variables here, for example:
uint64_t x = data[5];
// race condition sometimes (x sometimes not consistent)
}
奇怪的是,当我向每个线程添加__sync_synchronize()时,竞争条件就会消失。 我已经看到这发生在两个不同的服务器上。
即当我将代码更改为如下所示时,问题就消失了:
线程1(发布):
// set various shared variables here, for example
data[5] = 10;
__sync_synchronize();
uint64_t a = b.exchange(1); // signal to thread 2 that data is ready
线程2(接收):
if (b.load() != 0) { // signal that data is ready
__sync_synchronize();
// read various shared variables here, for example:
uint64_t x = data[5];
}
为什么需要__sync_synchronize()? 由于我认为交换和加载都可以确保逻辑的正确顺序,因此这似乎是多余的。
架构是x86_64处理器,Linux,G ++ 4.6.2
虽然无法通过简化的代码说出实际应用程序中实际发生了什么,但是__sync_synchronize
帮助,并且该函数是内存障碍的事实告诉我,您在一个线程中编写东西,而另一个线程以一种非原子的方式阅读。
一个例子:
thread_1:
object *p = new object;
p->x = 1;
b.exchange(p); /* give pointer p to other thread */
thread_2:
object *p = b.load();
if (p->x == 1) do_stuff();
else error("Huh?");
这很可能触发线程2中的错误路径,因为当线程2读取新的指针值p时, p->x
的写入实际上尚未完成。
在这种情况下,在thread_1代码中添加内存屏障应该可以解决此问题。 请注意,在这种情况下,thread_2中的内存屏障将无法执行任何操作-它可能会更改时间并似乎可以解决问题,但这并不是正确的选择。 如果您正在读取/写入两个线程之间共享的内存,则可能仍然需要两侧都有内存屏障。
我了解这可能并不完全是您的代码正在执行的操作,但是概念是相同的__sync_synchronize
确保在该函数调用之前,所有指令的内存读取和内存写入均已完成[这不是真正的函数调用,它将内联一条指令,等待任何未完成的内存操作完成]。
值得注意的是,对std::atomic
操作仅会影响存储在atomic对象中的实际数据。 不读取/写入其他数据。
有时,您还需要一个“编译器屏障”,以避免编译器将内容从操作的一侧移到另一侧:
std::atomic<bool> flag(false);
value = 42;
flag.store(true);
....
另一个线程:
while(!flag.load());
print(value);
现在,编译器有可能生成第一种形式,如下所示:
flag.store(true);
value = 42;
现在,那不是很好,是吗? std :: atomic肯定会成为“编译器障碍”,但在其他情况下,编译器可能会以类似的方式很好地摆弄东西。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.