2011-11-17 86 views
1

我在程序中成功使用了Concurrency::concurrent_unordered_map(這是由Microsoft制定的實現)。這是需要的,因爲多個元素的插入/更新和非常罕見的刪除是以併發方式執行的。並行容器 - 在元素擦除時同步

我知道這個容器(與所有其他併發容器一樣)提供了一個不安全的erase()方法 - 用於擦除節點。

您認爲最好的方法是使擦除過程也是線程安全的嗎?這種情況很少像我剛纔所說的那樣發生(僅僅是因爲用戶干預),而且我不太喜歡在每次對容器執行搜索時都必須輸入一個關鍵部分(或者對於其他任何操作,如迭代器遍歷和節點更新)。你怎麼看?我也在考慮基於事件的機制,但我不明白這在這裏如何適用。

+0

鎖定用互斥的部分,從容器中清除,開鎖。 –

+0

互斥體的唯一問題是,似乎必須在同一個互斥體中包含對容器所做的所有其他更新:所以對元素的所有插入,迭代器遍歷更新都必須由相同的互斥體保護。我寧願選擇另一種解決方案 – Ghita

+0

好吧,你必須將擦除函數包裝到'sync_erase()'中,並且保證客戶*只調用該函數。然後你只把互斥鎖放在那裏。 –

回答

2

事實上,一個關鍵部分的參與使得擦除過程併發安全地破壞了在我的情況下使用併發容器的目的。如果使用這種方法,每個與併發容器相關的操作都必須由相同的鎖來保護(即,直到現在不必踩到彼此腳趾的操作現在必須等待相同的臨界區)。所以這是迄今爲止最糟糕的想法,它會使您的併發容器在您可能使用它的每種情況下都毫無用處。

解決上述不便之處的想法是使用Reader Writer鎖。這允許共享讀取但獨佔寫入。每個人都應該保護刪除與一個作家鎖和所有其他操作與地圖上的閱讀器鎖是這樣的:

InsertOperation(key) -- this inserts the key in case is not present (and constructs a default constructed value) 
    { 
     reader_writer_lock::scoped_lock_read guard(reader_writer_lock); 
     ... 
    } 

    value Find(key) 
    { 
     reader_writer_lock::scoped_lock_read guard(reader_writer_lock); 
     ... 
    } 

    void EraseElement(key) 
    { 
     reader_writer_lock::**scoped_lock** guard(reader_writer_lock); 
     ... 
    } 
+1

插入是讀操作? – Dani

+0

其實是的,在遍歷,迭代器訪問,插入的意義上都是併發的在這個容器中安全 – Ghita

+0

@Dani。我更正了插入簽名,因爲它實際上做的是在哈希容器中插入一個鍵/值,以防鑰匙不存在 – Ghita

0

另一種解決方案,它應該工作得非常好的,我覺得進入EraseElement(key)時,將觸發一個事件和在程序結束時重置。這種方式在繼續之前,其他所有操作都必須等待該事件。我認爲這可能會提供與我以前的解決方案相同的性能水平。