2013-10-30 63 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

底一樣,不聰明是使用揮發性儘量保證線程安全,使用適當的