我的类中有一个volatile bool'play'标志,由一个线程设置并被另一个线程读取。
我是否需要同步对该标志的调用?例如在这个函数中:
void stop()
{
play = false;
}
在Windows中他们有_InterlockedExchange,OSX有OSAtomicAdd64Barrier,我看到那些函数与共享原语一起使用,我需要它们吗?
谢谢
答案 0 :(得分:3)
是的,volatile
并不以任何方式暗示线程安全或原子。如果可以,请使用std::mutex
和std::unique_lock
等,而不是平台细节。 std::atomic
是不错的选择 - 在这种情况下甚至可能是最好的。
答案 1 :(得分:1)
取决于:
如果您使用的是具有总存储顺序内存模型的CPU(例如x86 / x64)或任何只有1个CPU内核的计算机,那么您的问题的答案是肯定的,因为您声明只有1个线程写入标志和屏障指令可能在x86上无论如何都要优化掉。如果在具有宽松内存模型的CPU上编译相同的代码,则情况会发生变化,然后您可能会发现在x86上完美运行的代码会产生一些奇怪且难以重现的错误,如果您在ARM上编译并运行它或者PPC例如
volatile
指令阻止写入缓存,并且可能意味着读取线程比volatile
指令中的写入更快地看到写入。是否要使用此取决于此间隔的重要程度
答案 2 :(得分:0)
这取决于线程之间是否存在任何其他数据。线程的问题是,一个线程可能看到来自不同线程的写入的顺序与最初使用它们的线程不同。在这种情况下,您需要使用某种_Interlocked * / Atomic函数或锁定(在两个线程中),它们保证在标志之前所做的所有更改都对另一个线程可见。
如果没有其他共享数据(或只有只读共享数据),或者您在x86上运行,则仅使用volatile
也应该有效。然而,它在某种意义上是偶然的,并且不受任何标准的保证,因此如果您的平台支持它,仍然建议使用某种形式的Atomic / interlocked / etc.在将来(即一旦有良好的编译器支持),您应该使用C ++ 11的std::atomcic
,因为它可以在平台之间移植。
您不应该使用裸的非易失性变量,如果您这样做,编译器可能会决定优化检查。 volatile
与缓存无关,正如camelccc所暗示的那样。