2010-03-04 99 views
4

我有一個std :: vector < ...>它在兩個線程中共享。在MacOSX上,使用g ++,是std :: vector .size()線程安全嗎?

他們都調用vec-> size();

這可能是競爭條件的來源嗎?我希望不是因爲vec-> size()是常量。

謝謝!

+1

僅供參考:Mac OS X上gcc 4.2上的'size()'實現爲'size_type size()const {return size_type(this - > _ M_impl._M_finish - this - > _ M_impl._M_start); }'。 – kennytm

+0

你從哪裏找到這個?開導我。 – anon

+0

標準頭文件位於「/ usr/include/C++/*」目錄下,從實際包含「」的文件開始,並繼續閱讀包含的文件,直到找到「」爲止g ++用於存儲實際向量實現的通用頭文件(其中''是'bool'專業化的,以及其他用於實用函數的頭文件) –

回答

4

如果您致電只有vec->size()您是安全的。但這是難以置信的。只要你打電話給任何改變方法,如push_back種族可能會導致錯誤的大小。

1

可能不是。問題不在vec-> size()中,它也在所有其他函數中。

想一想:vector :: size()通常是直接從成員中計算出來的,例如, .end - .begin。現在在一個線程上push_back會發生什麼?它顯然會通過成員影響規模。它改變了記憶。但是沒有記憶障礙。其他內核上的其他線程只會看到舊的內存。因此,當他們撥打size()時,將使用舊值進行計算。

一個明顯的例外是在創建線程之後向量不改變大小。線程永遠不會有過時的信息。參考文獻:

+0

我完全同意這一點。當你編寫多線程代碼時,你應該努力使你的操作成爲原子。即使這種操作本身是安全的,如果您正在使用互斥鎖或其他操作的關鍵部分,則您也必須使用它們。如果你擔心性能上的問題,可以使用讀者作者鎖來使多個讀者能夠調整大小(),但只有一個單獨的作者。 – iain

+0

其實size()不訪問成員。它不會崩潰,可能發生的更糟糕的事情是過時的結果。看到我的答案。在某些情況下,可以使用過時的值,例如向用戶顯示代表容器大小的進度條。這很好,因爲您不想在容器上迭代,如果值過時,則在顯示的下一次刷新時它將是正確的。 – Aurelien

+2

@Aurelien:你所聲稱的與KennyTM的第一條評論直接相抵觸,這清楚地表明gcc 4.2可以訪問'_M_finish'和'_M_start'成員。如果另一個線程更改重新分配向量,那麼會產生一個_negative_大小,並從新的_M_finish中減去舊的_M_start。將該否定結果轉換回'size_type',並且您的值非常大。是的,繪製一個40億像素寬的進度條可能會導致一些麻煩。 – MSalters

相關問題