2011-11-17 45 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)时,将触发一个事件和在程序结束时重置。这种方式在继续之前,其他所有操作都必须等待该事件。我认为这可能会提供与我以前的解决方案相同的性能水平。