2011-06-28 85 views
0

我有2個線程(使用boost線程庫)和Windows上的全局矢量(visual studio 2005)。我創建了線程 - 首先是讀取文件(vector.push_back(value))並增加「讀取計數器」,另一個是處理已經加載的數據(第二個「指針」記住已經處理的向量中的索引)。處理是類似於vector[i] = function(vector[i]);同時讀取和寫入向量導致異常

當我啓動程序時,它以異常結束Unhandled exception at 0x0041350c in program.exe: 0xC0000005: Access violation writing location 0x00b82214.讀取計數器的值小於記錄計數(仍然讀取文件),vector.size()爲「readCounter + 1」,「處理指針」 +/- 2200(少得多然後讀計數器 - 在讀取空值沒問題)...值是不同的每次運行(有時,沒有拋出異常,並且程序完成)...

當我刪除處理行(vector[i] = function(vector[i]);)沒有問題發生...所以我猜,向量不是線程安全的。你能幫助我,如何預防這個問題?

+0

使事情線程安全補充說,是不是在大多數情況下需要顯著開銷。您應該*總是*假定標準庫不是線程安全的。 –

回答

0

,所以我想,矢量不是線程安全的。

當然,std :: vector不是線程安全的(標準容器都不能保證是線程安全的 - 但是它們的所有方法都保證可以被每個理智的實現重入)。你必須使用同步機制(互斥體等)。

5

標準(C++ 03)的當前版本甚至不支持線程的,所以實際上STL容器是線程安全與否完全取決於具體的實施。

在你的情況,你應該參考MSDN,其中指出,

單個對象是線程安全從多個線程讀取this page。例如,給定一個對象A,同時從線程1和線程2讀取A是安全的。

如果一個對象正由一個線程寫入,那麼所有的讀取和寫入該對象相同或其他線程必須得到保護。例如,給定一個對象A,如果線程1正在寫入A,則線程2必須被阻止讀取或寫入到A.

因此,您必須使用互斥鎖或一些保護您的讀/寫其他同步原語。您可以在Boost.Thread(順便提一下C++ 0x中的線程支持所基於的庫)中找到它們的多平臺和C++友好的實現。


順便說一句,如果你曾經使用VC的早期版本++(如2003),請記住,在這些版本中同時存在多線程和可用的標準庫的singlethread版本。如果您在應用程序中使用線程和CRT設施,則永遠不要使用CRT的單線程版本,請始終檢查項目設置以查看是否選擇了正確的版本。

0

向量是一個可增長的數據結構。當然,你不能分配任意大的內存,所以實現分配一個固定大小的內存(你可以在構建時設置)。隨着你的元素進入你的矢量它填補了這個空間。當它到達預分配空間的末尾時,它必須分配一個更大的塊(通常是原始大小的兩倍)並複製其中的所有數據。它還必須更新塊開始的內存位置並釋放舊分配的空間。

在你嘗試寫一些價值不屬於你了一個內存地址同時...

如果你知道它會如何發展大你可以預先分配所有存儲它需要。這有額外的好處,它不必一次又一次複製它,因爲它的尺寸翻了一番。

見:vector::vectorvector::capacityvector::reserve

+0

即使向量不增長,它也包含內部狀態,因爲它在更新時不能保證線程安全。不良後果的機會減少但並未消除。 –

+0

不能保證,但通常工作正常,猜測取決於實際的實現(因爲標準沒有對此做任何說明)...它必須更新向量的大小,但它存儲在機器字中,所以更新應該是原子的。 –

+0

更新尺寸可能是原子的,但仍然可能會遇到麻煩。例如,假設在插入新元素之前更新了大小?當實現可能隨下一個編譯器版本發生變化時,我不想依賴實現細節。 –