并发散列集<T>在 .NET 框架中? [英] Concurrent HashSet&lt;T&gt; in .NET Framework?

查看:18
本文介绍了并发散列集<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 Framework 不提供内置的并发散列集类型.但是,有一些解决方法.

Your implementation is correct. The .NET Framework does not provide a built-in concurrent hashset type, unfortunately. However, there are some workarounds.

ConcurrentDictionary(推荐)

第一个是使用名称空间System.Collections.Concurrent 中的类ConcurrentDictionary.在这种情况下,该值毫无意义,因此我们可以使用一个简单的 byte(内存中的 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 相同的优点,但键和值是不同的对象.

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.

来源:社交 MSDN

ConcurrentBag

如果你不介意重复的条目,你可以在上一个类的相同命名空间中使用 ConcurrentBag 类.

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 为您提供的其他线程安全方式来实现您自己的数据类型.这是一个很好的例子:如何在 .Net 中实现 ConcurrentHashSet

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 没有正式的并发访问,即使是读取操作.

The only drawback of this solution is that the type HashSet<T> doesn't officially concurrent access, even for reading operations.

我引用了链接帖子的代码(最初由 Ben Mosher 编写).

I quote the code of the linked post (originally written by Ben Mosher).

using System;
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
    }
}

将入口锁方法移到 try 块之外,因为它们可能引发异常并执行 finally 中包含的指令块.

Move the entrance lock methods ouside the try blocks, as they could throw an exception and execute the instructions contained in the finally blocks.

这篇关于并发散列集<T>在 .NET 框架中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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