并发的HashSet< T>在.NET框架? [英] Concurrent HashSet<T> in .NET Framework?

查看:186
本文介绍了并发的HashSet< T>在.NET框架?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下的类。

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆