咨询区
Sebastian
在 .NET 框架中并没有线程安全的 ConcurrentHashSet
类,我想模仿 ConcurrentDictionary
来实现一个,目前写了一下桩代码。
public class ConcurrentHashSet<TElement> : ISet<TElement>
{private readonly ConcurrentDictionary<TElement, object> _internal;public ConcurrentHashSet(IEnumerable<TElement> elements = null){_internal = new ConcurrentDictionary<TElement, object>();if (elements != null)UnionWith(elements);}public void UnionWith(IEnumerable<TElement> other){if (other == null) throw new ArgumentNullException("other");foreach (var otherElement in other)Add(otherElement);}public bool Add(TElement item){return _internal.TryAdd(item, null);}// I am not sure here if that fullfills contract correctlyvoid ICollection<TElement>.Add(TElement item){Add(item);}public bool Contains(TElement item){return _internal.ContainsKey(item);}public bool Remove(TElement item){object ignore;return _internal.TryRemove(item, out ignore);}public int Count{get { return _internal.Count; }}public IEnumerator<TElement> GetEnumerator(){return _internal.Keys.GetEnumerator();}
}
我不确定这代码能否在 foreach 中还能保证原子性,请问是否有更好的实现?
回答区
Ben Mosher
我最近遇到了类似的场景,不过我更关注的更高性能的 Add,Contains,Remove
方法,下面是我的实现。
using System.Collections.Generic;
using System.Threading;namespace BlahBlah.Utilities
{public class ConcurrentHashSet<T> : IDisposable{private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);private readonly HashSet<T> _hashSet = new HashSet<T>();#region Implementation of ICollection<T> ...ishpublic bool Add(T item){try{_lock.EnterWriteLock();return _hashSet.Add(item);}finally{if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();}}public void Clear(){try{_lock.EnterWriteLock();_hashSet.Clear();}finally{if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();}}public bool Contains(T item){try{_lock.EnterReadLock();return _hashSet.Contains(item);}finally{if (_lock.IsReadLockHeld) _lock.ExitReadLock();}}public bool Remove(T item){try{_lock.EnterWriteLock();return _hashSet.Remove(item);}finally{if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();}}public int Count{get{try{_lock.EnterReadLock();return _hashSet.Count;}finally{if (_lock.IsReadLockHeld) _lock.ExitReadLock();}}}#endregion#region Disposepublic void Dispose(){if (_lock != null) _lock.Dispose();}#endregion}
}
点评区
实现一个 ConcurrentSet<T>
其实蛮有必要的,你在 github 或者其他第三方网站上会找到很多类似的 ConcurrentSet<T>
的实现,比如:https://pastebin.com/8REHRFFL