2012-02-16 274 views
6

我正在使用std :: vector作爲多線程應用程序中的共享數據。我封裝螺紋的類中,例如,std ::向量,線程安全,多線程

class ABC { 
public: 
    double a, b, c; 
}; 

boost::mutex mutex1; 

class XYZ { 
public: 
    XYZ(vector<ABC> & pVector) { 
     ptrVector = &pVector; 
     m_thread = boost::thread(&XYZ::Start, this); 
    } 
    ~XYZ() {} 
    void Start(); 
public: 
    vector<ABC> * ptrVector; 
    boost::thread m_thread; 
};  

void XYZ::Start() { 
    try { 
     while(1) { 
      boost::this_thread::interruption_point(); 
      for (unsigned int i=0; i<ptrVector->size(); i++) { 
       { 
        boost::mutex::scoped_lock lock(mutex1); 
        ptrVector->at(i).a = double(rand())/10000; 
        ptrVector->at(i).b = double(rand())/10000; 
        ptrVector->at(i).c = double(rand())/10000; 
       } 
      } 
     } 
    } 
    catch(boost::thread_interrupted) {} 
    catch(std::exception) {} 
} 

當我關閉應用程序,有時,在調試,會有2個錯誤消息,有時會有任何錯誤消息。我經常聽到人們在談論std :: vector不是線程安全的,這是這種情況之一嗎?我正在使用Visual Studio 2008,boost線程,矢量的大小是固定的。任何人都可以提供一些關於如何在多線程應用程序中使用std :: vector的建議。在ETP.exe 0x7688b9bc

  1. 第一次機會異常:微軟C++ 例外:的std :: out_of_range內存位置0x02d8f7bc ..在ETP.exe 0x00e916e0
  2. 第一次機會異常:0000005:訪問 違規閱讀地點0x00000008。
  3. 第二次機會斷言失敗:文件C:\ Program Files文件 (x86)的\微軟的Visual Studio 9.0 \ VC \包括\載體,線路二 機會斷言失敗:文件C:\ Program Files文件(x86)的\微軟 視覺studio 9.0 \ vc \ include \ vector98

謝謝。

+0

矢量不是線程安全的,如果你嘗試從不同的線程同時那麼它將打破寫入。儘管你正在鎖定它,並且沒有其他代碼來查看你是如何使用它的,但是不可能知道可能發生了什麼問題。這個特殊的代碼本身看起來很好。 – Jarryd 2012-02-16 04:06:13

+0

除了線程安全之外,您可能還需要考慮線程訪問向量的順序,如果一個線程正在讀取向量,那麼您應該確保另一個線程已經寫入向量或至少您的代碼應該處理矢量尚未寫入的條件。 – 2012-02-16 04:13:53

+0

@Jarryd你是儀式,在這段代碼中,似乎他使用互斥鎖來鎖定向量,如果他這樣做,那麼它不應該引起問題,因爲我們需要去完成代碼的細節 – 2012-02-16 04:14:44

回答

22

其實,它絕對是毫無意義的狀態X是或不是線程安全的!你需要符合什麼樣的用途。例如,幾乎任何類在某種線程中以某種方式使用並在另一線程中被銷燬時都不會「線程安全」。

也就是說,std::vector<T>不是線程安全的,獨立於它重複的頻率是錯誤。但是,似乎大多數人既不理解也不欣賞給出的線程安全保證。 std::vector<T>在以下意義上是線程安全的:

  • 您可以同時從多個線程中讀取矢量對象。
  • 如果有一個線程更改矢量對象,則不應該有併發讀者或寫者。
  • 訪問矢量對象不會干擾其他矢量對象。

這適用於向量結構本身。對包含對象的訪問必須遵守施加於其上的任何規則。這些顯然不是許多人想到的線程安全保證,但更強大的東西不能用於容器接口。

+0

感謝您的意見。現在我對此更加清楚了。 – 2607 2012-02-21 04:29:37

+0

對不起,但完全不同意你的看法,線程安全是一個已知的定義,指出實現應該保證併發(線程)保護它的共享區域以避免衝突,這意味着一個類是線程安全的或者不是,說明它取決於使用意味着它不是線程安全!,這怎麼能是正確的答案? – Cross 2017-02-21 18:50:33

+0

您可以同時從多個線程讀取。是的 - 只要在上次修改後發佈了釋放內存屏障,並且在所有讀取線程上都出現了匹配的獲取內存屏障...... – Persixty 2017-05-04 10:38:40

4

您可以先致電ptrVector->size(),而不要先將其鎖定。這很容易成爲你問題的原因。確保在讀取或寫入之前鎖定您的矢量。

+1

他說大小矢量是固定的,所以不應該引起問題。但是,由於我們沒有更多的代碼,我們不知道他是否在不知道的情況下以線程不安全的方式添加它。 – Jarryd 2012-02-16 05:16:19