以下是创建将由多个线程访问的并发hashset对象的示例。 “添加”和“删除”方法都通过锁定对象_threadLock锁定。我是否需要为每种方法单独使用_threadLock,或者我可以像下面那样分享它吗?
public class ConcurrentHashset<T>
{
private readonly HashSet<T> _hash = new HashSet<T>();
private readonly object _threadLock = new object();
public bool Add(T itemToAdd)
{
lock (_threadLock)
{
return _hash.Add(itemToAdd);
}
}
public bool Remove(T item)
{
lock (_threadLock)
{
return _hash.Remove(item);
}
}
public bool Contains(T item)
{
return _hash.Contains(item);
}
}
答案 0 :(得分:4)
两个操作应该共享同一个锁。
否则,可以将对Add
的呼叫与另一个Remove
的呼叫交错,这可能会导致损坏的哈希集。
此外,即使Contains
只读取散列集但没有写入散列集,它也需要在锁定内部执行此操作 - 否则可能会冒险读取当前由{{写入的散列集“。 1}} / Add
因此处于不一致状态。
(另外,并发Remove
的简单实现是为HashSet<T>
提供一个简单的包装器,我们只是忽略这些值。注意ConcurrentDictionary<T, TValue>
是无锁的。 )
答案 1 :(得分:0)
当然必须共享锁,否则首先锁定是没有意义的。
如果您正在访问要读取的项目并同时访问该项目以进行删除,则事情将无法正常进行。