2013-08-16 41 views
3

我正在創建這個多線程C++程序,並且在編譯版本模式時,我找到了類錯誤(對象仍爲空),即它看起來像缺少volatile標記。一切都很不穩定

但問題是,因爲有第二個工作線程觸及各種對象,這意味着在程序中虛擬一切都是不穩定的

我不知道是否有一種方法來關閉在蘋果LLVM編譯器創造volatile關鍵字是專爲修正錯誤的優化。這些錯誤不會在調試模式下顯示(因爲優化已關閉)。 volatile處處基本上意味着在每個共享變量聲明前加入volatile,成員函數,並加上volatile

我想我寧願損失volatile優化,因爲我忘記標記volatile,所以冒險出現一個虛假的bug。

+10

如果在優化模式下出現錯誤,但未在調試模式下顯示,則表示程序不正確。如果有的話,我會後悔的是,錯誤沒有在調試模式下顯示出來,因爲在你的代碼中有一個競爭條件,你無法捕捉到。 – dasblinkenlight

+3

不要在多線程中使用volatile(更好地使用std庫,例如std :: atomic):http://software.intel.com/zh-cn/blogs/2007/11/30/volatile-almost-useless-爲多線程編程 – user1837009

+0

嗯,這很清楚發生了什麼。我有一個'vector'數組,它顯示爲空,即使它已被初始化。 – bobobobo

回答

7

在C++中,volatile與線程安全無關。你不能依靠它來避免數據競賽。它的目的是強制同步訪問變量(來自單個線程,或使用其他某種機制相互同步的線程)以完全按照指定的順序進行訪問。當與硬件交互時,這通常是必要的,以防止似乎無所事事,但實際上影響硬件狀態的訪問不被優化。它不保證訪問的未同步的效果。

爲避免數據競爭,您必須使用原子操作或顯式鎖定來同步對共享對象的訪問。 C++ 11在標準庫中提供了這些功能;如果你陷入過去,那麼你將不得不依賴於你的平臺上的任何庫(如pthreads)或語言擴展(如原子內在函數)。

+0

我知道。我只是詢問在工作線程上初始化的類級變量在主線程上是否會顯示爲_still uninitialized_(假設我已正確鎖定訪問權限)。我認爲'volatile'意味着不要緩存這個值,因爲它可能在你上次讀取它之後在另一個線程上發生了變化。 – bobobobo

+0

@bobobobo:如果你看到了,那麼訪問沒有被正確鎖定。 'volatile'表示對變量的所有訪問將按照線程中指定的順序進行;它不會保證修改會傳播到另一個線程,或者如果它發生了原子化,它將顯示爲原子。 'volatile'不能用於線程安全,因爲這不是它的設計目的。 –

+0

那麼你會很高興知道這個bug是由於一個非常罕見的'nan'條件造成的。我在譴責線索,因爲我一直對他們懷疑。啊錯了。 – bobobobo