我需要在c++中同步原语吗?



我在我的类中有一个易失性bool 'play'标志,由一个线程设置并由另一个线程读取。

我需要同步对该标志的调用吗?例如在这个函数中:

void stop() 
{
   play = false;
}

在windows中,他们有_InterlockedExchange和OSX有OSAtomicAdd64Barrier,我已经看到这些函数与共享原语一起使用,我需要它们吗?

谢谢

是的,volatile在任何方面都不意味着线程安全或原子。如果可以,使用std::mutexstd::unique_lock等,而不是平台细节。std::atomic是一个很好的选择——也许在这种情况下是最好的。

取决于:

如果你是在一个CPU的总存储顺序内存模型(如x86/x64)或任何机器只有一个CPU核心,那么你的问题的答案是没有给定的,你说只有1个线程写的标志,屏障指令可能是优化掉了x86。如果您在具有宽松内存模型的CPU上编译相同的代码,那么情况就会发生变化,然后您可能会发现在x86上完美运行的代码在ARM或PPC上编译和运行时会出现一些奇怪且难以重现的错误,例如

volatile指令防止写操作被缓存到某个地方,这可能意味着读线程看到写操作的速度要比没有volatile指令快得多。是否使用这个取决于这个间隔的重要性

这取决于线程之间是否有任何其他数据共享。线程的问题是,一个线程可能以不同的顺序看到来自不同线程的写操作,而不是线程最初发出写操作的顺序。在这种情况下,您需要使用某种_Interlocked*/Atomic函数或锁(在两个线程中),它们保证在标志之前所做的所有更改对另一个线程可见。

如果没有其他共享数据(或只有只读共享数据),或者运行在x86上,只使用volatile也应该可以工作。然而,从某种意义上说,它的工作只是偶然的,没有任何标准保证,所以如果你的平台支持它,仍然建议使用某种形式的Atomic/interlocked/等。在未来(即一旦有了良好的编译器支持),你应该使用c++ 11的std::atomcic,因为它将在平台之间可移植。

您不应该使用裸的非易失性变量,如果这样做,编译器可能会决定优化检查。volatile与camelccc建议的缓存关系很小。

相关内容

  • 没有找到相关文章

最新更新