簡體   English   中英

C ++線程安全vector.erase

[英]C++ Thread safe vector.erase

我為SFML寫了一個線程渲染器,它使用指向可繪制對象的指針並將其存儲在向量中以繪制每幀。 開始將對象添加到向量中並將對象移除到向量中時,經常會導致分段錯誤(SIGSEGV)。 為了解決這個問題,我將需要刪除/添加的對象添加到隊列中,以便稍后刪除(在繪制框架之前)。 這似乎可以解決問題,但是最近我注意到,如果一次添加多個對象(或添加/刪除它們的速度足夠快),我將獲得相同的SIGSEGV。

從向量添加/刪除向量時應該使用鎖嗎?

您需要了解C ++標准(以及可能存在的並發系統的C ++ 2003實現)提供的線程安全保證。 在以下意義上,標准容器是線程安全的:

  1. 可以有多個並發線程讀取同一個容器。
  2. 如果有一個線程正在修改一個容器,則不應有並發線程讀取或寫入同一容器。
  3. 不同的容器彼此獨立。

許多人誤解了容器的線程安全性,意味着這些規則是由容器實現強加的:不是! 遵守這些規則是您的責任。

這些不是,實際上不能由容器強加的原因是,它們沒有適合於此的接口。 例如,考慮以下瑣碎的代碼:

if (!c.empty() {
    auto value = c.back();
    // do something with the read value
}

容器可以控制對empty()back()的調用的訪問。 但是,在這些調用之間,它必然需要釋放任何類型的同步工具,即,在線程嘗試讀取c.back() ,容器可能再次為空! 本質上有兩種方法可以解決此問題:

  1. 如果並發線程可能會更改容器以跨越某種形式相互依賴的整個訪問范圍,則需要使用外部鎖定。
  2. 您將容器的界面更改為監視器 但是,容器接口根本不適合朝這個方向更改,因為監視器本質上僅支持“即發即棄”風格的接口。

兩種策略都有其優勢,並且標准庫容器顯然支持第一種樣式,即,在同時使用時需要外部鎖定,並且可能至少有一個線程修改該容器。 如果一開始只使用一個線程,則它們不需要任何類型的鎖定(內部或外部)。 這實際上是他們設計的方案。 為它們提供的線程安全性保證是適當的,以確保沒有使用不是線程安全的內部設施,例如每個對象迭代器對象或由多個線程共享但不具有線程安全性的內存分配設施,等等。 。

要回答原始問題:是的,如果您在一個線程中修改容器並在另一個線程中讀取它,則需要使用外部同步,例如以互斥鎖的形式。

從向量添加/刪除向量時應該使用鎖嗎?

是。 如果您同時使用兩個線程中的向量並重新分配,則備用分配可能會換出並在另一個線程的腳后釋放。 另一個線程將讀取/寫入釋放的內存,或正在使用的內存用於另一個不相關的分配。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM