簡體   English   中英

多線程訪問C ++中的std :: map

[英]Multiple threads accessing std::map in c++

我正在編寫各種Minecraft副本,我真的想為世界生成,更新塊,光傳播等實現多線程。我將所有加載的塊存儲在哈希映射“ chunk_map”中。

將互斥鎖放在chunk_map上會破壞多線程的全部目的,因為每個線程的大部分工作都是在chunk_map上進行迭代。

如果我的想法是正確的,那么在映射中插入新塊應該沒問題(在最壞的情況下,線程可能會跳過剛剛添加的塊),但是刪除塊肯定是一個問題。

制作使用shared_ptr而不是iterator_type的哈希映射實現是否可以解決在其他線程對該映射進行迭代的同時從映射中刪除am元素的問題? 還是有其他更簡單的方法?

編輯:我想避免完全同步線程,因為我不希望世界產生,阻止更新等限制渲染性能。

我希望主線程呈現當前已加載的所有塊。 我還希望“更新程序線程”更新每個已加載塊中的每個塊,等等。還有“世界線程”以加載和卸載塊。

不幸的是,您的問題基於錯誤的前提:

如果我的想法是正確的,那么在映射中插入新塊應該沒問題(在最壞的情況下,線程可能會跳過剛剛添加的塊),但是刪除塊肯定是一個問題。

不你錯了。 最壞的情況遠不止於此。 考慮:

  1. 線程A構造了一個新塊。
  2. 線程A將該塊添加到映射中。
  3. 線程B在映射中看到新塊的條目。
  4. 線程B嘗試訪問該塊,但是由於代碼和對寫入進行重新排序的硬件的優化,它看不到步驟1中創建的寫入線程A。

oom,您的程序剛崩潰。

推理中的關鍵缺陷(這是非常普遍的缺陷,如果您想成為一名成功的程序員,則必須在推理中加以修正)認為,如果您違反明確的規則,唯一可能出錯的事情就是可以預見。 這條推理路線絕對是計算機編程領域的死法。

因此,實際上,絕對最壞的情況甚至比我上面所說的還要糟糕。 您違反了正在使用的類的要求,該類的實現會因平台而異。 絕對沒有辦法知道出什么問題了。

您可以在多個線程上(使用std::packaged_taskstd::async )生成塊(更新塊或其他內容),然后使用主線程將結果復制到映射中。

在您的案例中,最長的部分不是地圖訪問,而是數據處理。

容器的規范需要深入閱讀才能使容器確定哪些寫操作需要互斥,哪些讀操作即使在寫操作期間也應該是安全的。

[啊你說的哈希圖]

簡而言之:

哈希圖,向量和字符串是一種痛苦。 可以做一些使對象指針保持良好狀態的事情(例如預分配),但是即使是單線程,在插入或刪除之后也很難保持引用。

對於傳統地圖,集合,列表:

顯然,容器的構造和破壞必須是排他的。

當然,如果您不對地圖進行任何修改,則可以根據需要隨意進行多線程讀取。 只要使用find()而不是operator [],就可以了。

map和list的行為如果要插入新對象,則任何現有的迭代器都將保持有效,但是在insert()期間(假設insert()成功),您將無法找到find()或next()(或其他迭代器算法) ,因此通常值得在插入之前進行查找),並且您不能並行執行多個(成功)插入。 因此,您需要一個作家多讀者鎖定模型:這可以像原子查找/迭代器++計數器和第一個/最后一個查找與任何插入/刪除互斥鎖一樣簡單。

如果要刪除,則,任何指向已刪除對象的迭代器都將變為無效,這在單線程中也是如此,但並行使用會帶來更多問題。 您的代碼需要絕對確定您沒有對已刪除元素的任何迭代器。 根據您刪除的用例,這可能不是問題,或者可能是設計殺手。 我不明白為什么您要刪除在另一個線程中仍需要/使用的資源,但是我也不知道您的代碼如何知道是否需要它。 例如,您可能需要在每個實例中使用原子使用計數器,以隨時知道哪些實例可以安全刪除。

如果您要進行其他變異操作,則必須做出自己的設計決策。 這些是主要操作,以及我認為它們使用安全的方式。

您可以通過更深入的了解來使其比以往更嚴格,但這通常是良好的性能與復雜性的折衷。

這適用於除vector和string以及hashmap之外的大多數容器,但出於不同的原因。 但這是因為即使在這兩種情況下,即使在單線程中,如果移動存儲,插入操作都將使現有迭代器完全無效,而插入和刪除操作會使索引較高的所有迭代器無效。 使用hashmap時,問題是在執行重新存儲桶操作之后,您之前幾乎所知道的一切都是無效的。

在這種情況下,使用map而不是hashmap可以更有效地鎖定,但是您必須確定log(n)的常規性能命中值是否值得該常規的低鎖定優勢。 或者,安排您的哈希圖僅包含指針,以便您的代碼可以安全地保留指向實際對象的指針,而不是迭代器或指向所包含對象的指針-這在哈希圖中並不安全,並且盲目鎖定所有索引調用。

暫無
暫無

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

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