我是否需要为每种方法单独使用线程锁?

时间:2015-08-17 17:13:31

标签: c# asynchronous locking

以下是创建将由多个线程访问的并发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);
    }
}

2 个答案:

答案 0 :(得分:4)

两个操作应该共享同一个锁。

否则,可以将对Add的呼叫与另一个Remove的呼叫交错,这可能会导致损坏的哈希集。

此外,即使Contains只读取散列集但没有写入散列集,它也需要在锁定内部执行此操作 - 否则可能会冒险读取当前由{{写入的散列集“。 1}} / Add因此处于不一致状态。

(另外,并发Remove的简单实现是为HashSet<T>提供一个简单的包装器,我们只是忽略这些值。注意ConcurrentDictionary<T, TValue>是无锁的。 )

答案 1 :(得分:0)

当然必须共享锁,否则首先锁定是没有意义的。

如果您正在访问要读取的项目并同时访问该项目以进行删除,则事情将无法正常进行。