2012-08-07 62 views
1

我有一個std::map < std::string, std::string >,它在一個線程中以不規則的間隔添加了值(但頻繁且需要非常快),並且偶爾會刪除一組條目。在插入其他線程時有效地迭代地圖

我需要從不同的線程將地圖的快照作爲文本轉儲到用戶的調試日誌命令。

顯然,它不是線程安全的,只是遍歷地圖輸出調試信息,而它可以更新,所以我目前正在採取一個讀鎖(互斥體)之前轉儲數據和每個插入或刪除寫鎖。這工作正常,但我無法真正鎖定地圖很長時間,它延遲了傳入更新的處理過多。

我不相信我可以鎖定和解鎖每個項目的調試轉儲線程,因爲從其他線程修改映射可能會使迭代器無效,我相信。

有沒有什麼辦法可以安全地做到這一點,而不必在整個數據結構上取出讀鎖,而我寫出來以便新值仍可以快速插入?我意識到如果在我迭代它的時候可以添加和刪除值,但是隻要理解它是安全的,我就無法得到一個保證一致的數據視圖。

如果沒有辦法爲此使用地圖,任何人都可以建議我可以使用的任何其他數據結構嗎?

編輯:我希望有一個解決方案,這意味着我不需要在添加項目時取出昂貴的鎖。

+0

我應該補充一點,我現在不能使用C++ 11。 – jcoder 2012-08-07 14:03:05

+7

你的「地圖」有多大?在I/O期間鎖定它可能會很昂貴,但是您可以製作映射副本(比寫入磁盤更快)並從副本執行I/O。這保證了輸出將在特定時刻反映地圖的狀態。 – Chad 2012-08-07 14:03:27

+0

通常有一百個左右的條目,但有時候可能會有幾百個或更多, – jcoder 2012-08-07 14:05:04

回答

4

有2個解決方案,我可以在這一刻看到:

  1. (簡單,但仍有可能要花很長時間):複製地圖(或分配給另一個容器),而被鎖定,然後傾倒本地副本到調試日誌,但未鎖定
  2. (更多工作):通過隊列將映射更新委託給另一個線程。如果另一個線程是轉儲到調試日誌的線程,那麼您不再需要這些鎖。這樣,快速線程只在訪問隊列時被鎖定。
+0

oooh解決方案二可能有效,重要的是這些地圖更新不會長時間擱置主線程,但不需要很快完成。 – jcoder 2012-08-07 14:19:32