想知道是否可以按照以下方式遍歷STL容器(如向量)以避免讀/寫鎖定,但只允許任何「寫入」線程執行push_back()操作。
不要,這不是線程安全的。考慮一個試圖讀取值並轉到當前緩衝區的線程。此時第二個線程正在增長緩衝區,在第一個線程獲得指向緩衝區的指針之後,但在它實際讀取值之前,第二個線程釋放緩衝區的內容。第一個線程正在讀取死對象,這是未定義的行爲。
將問題限制在一個reserve()
-ed向量中(即避免增長緩衝區的問題),該方法仍然不是線程安全的。在push_back()
的代碼會做類似的東西:
template <...>
class vector {
T *begin,*end,*capacity; // common implementation uses 3 pointers
void push_back(T value) {
if (end == capacity) { /* grow vector and insert */ }
else {
new (end) T(value);
++end;
}
}
};
這裏的問題是,沒有同步機制的編譯器可以重新排列的指示,增加end
並存儲到內存中,然後調用T
構造在緩衝件。如果重排序發生,那麼您的讀者線程可能會看到值size()
,其中包含當前正在存儲的值,但該值尚未存在於向量中。
我想這個問題的最後一句話是試圖說容量足夠大,永遠不會讓它改變(儘管顯然沒有用正確的術語說)。 – GManNickG 2013-03-12 20:30:10
@GManNickG準確地說。我不明白這個答案是否合格,如果容量足夠,它不應該增長?如果擔心某個特定的實現可能會修改緩衝區,那麼也許我應該只使用一個數組? – stgtscc 2013-03-12 21:40:40
@stgtscc:當矢量緩衝區不需要增長時增加了另一個潛在問題。 – 2013-03-12 21:54:49