2013-10-30 62 views
2

我对volatile的使用情况有疑问。我通常会尝试跨线程共享的所有变量都具有volatile关键字,以确保直接访问内存,并且当然通过互斥锁保护。多线程应用程序中的易失性C/C++

但是,如果共享变量以确保一致性,真的需要volatile吗?

我个例子来说:

Thread1: //(affects it behaviour with the variable) 
mymutex.lock(); 
if(variable) 
{ 
    ... 
    variable = false; 
} 
mymutex.unlock(); 

Thread2: 
mymutex.lock(); 
variable = true; 
mymutex.unlock(); 

在上例,仅thread2写入和thread1读/写。是否有可能缓存variable并且线程不读取新值?即使互斥体设置正确?在这种情况下,我需要volatile吗?

我在问这个,因为不是变量,我有一个std::vector,它不能变化。如果没有volatile关键字,我不能100%确定这种方法是安全的。

谢谢。

编辑:适当重新构造问题。

+6

只要你的变量访问由互斥保护 - [你没有使用'volatile']( http://stackoverflow.com/questions/11172922/does-stdmutex-create-a-fence) –

+0

所以,如果我得到您的评论。那么在锁释放后,所有在互斥体/信号量/ CriticalSection中访问的变量都会刷新并可见于其他线程? – DarkZeros

+0

@DarkZeros正好!这就是它的工作原理。 –

回答

5

volatile在C++中不适用于并发。这是关于是否允许编译器优化从读取变量或不读取。它主要用于诸如通过存储器映射与硬件接口的事物。

不幸的是,这意味着即使您确实有volatile变量,读取和写入仍然可以访问未同步的线程本地存储。另外,std::vector不是线程安全的。

因此,无论哪种情况,您都需要同步,例如使用std::mutex(您提到过)。现在,如果这样做了,受该mutex保护的变量不需要是volatilemutex本身进行同步,并防止您担心的问题类型。

+2

正确答案。我只想强调一下已经说过的内容:“volatile”不适用于线程同步。如果任何人使用volatile来同步线程,代码仍然不正确的可能性大于90%,但是会更慢。 Ofc在线程中使用volatile是有效的上下文,但很少,并且通常在实现低级同步基元(如自旋锁)时。 – ultimA

+0

谢谢。我发现了很多答案,都说“不要使用volatile来共享数据”。我显然不会在没有互斥量的情况下与易失性数据共享数据。我总是使用互斥锁来共享。我的问题是“数据是否没有易失性?”。这显然是我期待的。 – DarkZeros

+0

@DarkZeros所有你可以确保的是,如果你使用正确的同步,效果就好像来自不同线程的操作是交错的。它们如何交错,以及何时看到由另一个线程写入的值是无法控制的。但是,volatile不会改变这一点,所以添加它并不能解决这个问题。 – Agentlien

0

看看我的回答here

底一样,不聪明是使用挥发性尽量保证线程安全,使用适当的