并发的HashSet&LT; T&GT;在.NET框架? [英] Concurrent HashSet<T> in .NET Framework?
问题描述
我有以下的类。
class Test{
public HashSet<string> Data = new HashSet<string>();
}
我需要到外地数据,从不同的线程发生变化,所以我想在我的当前线程安全的实现一些意见。
I need to change the field "Data" from different threads, so I would like some opinions on my current thread-safe implementation.
class Test{
public HashSet<string> Data = new HashSet<string>();
public void Add(string Val){
lock(Data) Data.Add(Val);
}
public void Remove(string Val){
lock(Data) Data.Remove(Val);
}
}
有没有更好的解决方案,直接去现场和多线程保护它免受并发访问?
Is there a better solution, to go directly to field and protect it from concurrent access by multiple threads?
推荐答案
您的实现是正确的。 .NET框架不提供内置的并行HashSet的类型,很遗憾。不过,也有一些解决方法。
Your implementation is correct. The .NET Framework does not provide a built-in concurrent hashset type, unfortunately. However, there are some workarounds.
ConcurrentDictionary(推荐)
这第一种是使用类 ConcurrentDictionary&LT; TKEY的,TValue&GT;
命名空间中的 System.Collections.Concurrent
。在这种情况下,该值是没有意义的,所以我们可以用一个简单的字节
(内存1个字节)。
This first one is to use the class ConcurrentDictionary<TKey, TValue>
in the namespace System.Collections.Concurrent
. In the case, the value is pointless, so we can use a simple byte
(1 byte in memory).
private ConcurrentDictionary<string, byte> _data;
这是建议的选项,因为类型是线程安全的,并为您提供比 HashSet的&LT相同的优点; T&GT;
除键和值是不同的对象
This is the recommended option because the type is thread-safe and provide you the same advantages than a HashSet<T>
except key and value are different objects.
来源:<一个href=\"http://social.msdn.microsoft.com/Forums/vstudio/en-US/226c8fc0-4c6b-49d0-baf3-85c658d810eb/why-is-there-no-hashset-list-in-systemcollectionsconcurrency\">Social MSDN
ConcurrentBag
如果你不介意这是重复条目,可以使用类 ConcurrentBag&LT; T&GT;
在previous类相同的命名空间
If you don't mind about the duplicate entries, you can use the class ConcurrentBag<T>
in the same namespace of the previous class.
private ConcurrentBag<string> _data;
自实施
最后,像你一样,你可以实现你自己的数据类型,使用锁或其他方式在.NET为您提供是线程安全的。这里是一个很好的例子:如何实现ConcurrentHashSet在.net
Finally, as you did, you can implement your own data type, using lock or other ways that the .NET provides you to be thread-safe. Here is a great example: How to implement ConcurrentHashSet in .Net
该解决方案的唯一缺点是,键入的HashSet&LT; T&GT;
不正式的并发访问,甚至对读取操作
The only drawback of this solution is that the type HashSet<T>
doesn't officially concurrent access, even for reading operations.
我引用链接后(最初由本·莫舍编写)的code。
I quote the code of the linked post (originally written by Ben Mosher).
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)
{
_lock.EnterWriteLock();
try
{
return _hashSet.Add(item);
}
finally
{
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
}
}
public void Clear()
{
_lock.EnterWriteLock();
try
{
_hashSet.Clear();
}
finally
{
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
}
}
public bool Contains(T item)
{
_lock.EnterReadLock();
try
{
return _hashSet.Contains(item);
}
finally
{
if (_lock.IsReadLockHeld) _lock.ExitReadLock();
}
}
public bool Remove(T item)
{
_lock.EnterWriteLock();
try
{
return _hashSet.Remove(item);
}
finally
{
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
}
}
public int Count
{
get
{
_lock.EnterReadLock();
try
{
return _hashSet.Count;
}
finally
{
if (_lock.IsReadLockHeld) _lock.ExitReadLock();
}
}
}
#endregion
#region Dispose
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
if (_lock != null)
_lock.Dispose();
}
~ConcurrentHashSet()
{
Dispose(false);
}
#endregion
}
}
编辑:将入口锁定方法ouside的尝试
块,因为它们可能会抛出一个异常,并执行包含在<$的说明C $ C>最后块。
Move the entrance lock methods ouside the try
blocks, as they could throw an exception and execute the instructions contained in the finally
blocks.
这篇关于并发的HashSet&LT; T&GT;在.NET框架?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!