我爲SFML寫了一個線程渲染器,它將指針指向可繪製對象並將它們存儲在向量中以繪製每一幀。開始向矢量添加對象並將對象移除到矢量將經常導致分段錯誤(SIGSEGV)。爲了試圖解決這個問題,我會添加需要刪除/添加到隊列中的對象,以便稍後移除(繪製框架之前)。這似乎解決了它,但最近我已經注意到,如果我一次添加多個對象(或者添加/刪除它們足夠快),我會得到相同的SIGSEGV。C++線程安全vector.erase
我應該在向量中添加/刪除時使用鎖嗎?
我爲SFML寫了一個線程渲染器,它將指針指向可繪製對象並將它們存儲在向量中以繪製每一幀。開始向矢量添加對象並將對象移除到矢量將經常導致分段錯誤(SIGSEGV)。爲了試圖解決這個問題,我會添加需要刪除/添加到隊列中的對象,以便稍後移除(繪製框架之前)。這似乎解決了它,但最近我已經注意到,如果我一次添加多個對象(或者添加/刪除它們足夠快),我會得到相同的SIGSEGV。C++線程安全vector.erase
我應該在向量中添加/刪除時使用鎖嗎?
我應該在向量中添加/刪除時使用鎖嗎?
是的。如果您同時使用來自兩個線程的向量並重新分配,則後備分配可能會換出並釋放到其他線程的後面。另一個線程將讀取/寫入釋放的內存,或用於另一個無關分配的內存。
您需要了解線程安全性,以保證C++標準(以及可能的併發系統的C++ 2003的實現)給出。標準容器在以下意義上是線程安全的:
很多人誤解容器的線程安全的意思,這些規則是由容器實現地稅:他們都沒有!遵守這些規則是你的責任。
這些不是,實際上不能由容器強加的原因是它們沒有適合這個的接口。例如,考慮下面的瑣碎一段代碼:
if (!c.empty() {
auto value = c.back();
// do something with the read value
}
容器可以控制到empty()
和back()
接入到呼叫。然而,在這些調用之間,它必然需要釋放任何類型的同步設施,即在線程嘗試讀取c.back()
時容器可能再次變空!基本上有兩種方法來解決這個問題:
這兩種策略都有它們的優點,標準庫容器明顯支持第一種樣式,即當與至少一個修改容器的線程同時使用時,它們需要外部鎖定。如果首先只有一個線程使用它們,它們不需要任何類型的鎖定(無論是內部還是外部)。這實際上是他們設計的場景。爲它們提供的線程安全保證已經到位,以確保沒有內部工具不是線程安全的,比如每個對象迭代器對象或多線程共享的內存分配工具,而不是線程安全的,等等
要回答原始問題:是的,您需要使用外部同步,例如以互斥鎖的形式,如果您在一個線程中修改容器並在另一個線程中讀取它。
我認爲一個靜態鎖就足夠了。 –