如何实现一个线程安全的 ConcurrentHashSet ?
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何实现一个线程安全的 ConcurrentHashSet ?相关的知识,希望对你有一定的参考价值。
咨询区
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 correctly
void 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> ...ish
public 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 Dispose
public void Dispose()
if (_lock != null) _lock.Dispose();
#endregion
点评区
实现一个 ConcurrentSet<T>
其实蛮有必要的,你在 github 或者其他第三方网站上会找到很多类似的 ConcurrentSet<T>
的实现,比如:https://pastebin.com/8REHRFFL
以上是关于如何实现一个线程安全的 ConcurrentHashSet ?的主要内容,如果未能解决你的问题,请参考以下文章
HashMap与ConcurrentHashMap的区别(转)