首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在.Net 4.0中没有ConcurrentList<T>?

在.Net 4.0中没有ConcurrentList<T>?
EN

Stack Overflow用户
提问于 2011-07-07 03:06:48
回答 12查看 125.3K关注 0票数 214

我很高兴看到.Net 4.0中新的System.Collections.Concurrent名称空间,非常好!我见过ConcurrentDictionaryConcurrentQueueConcurrentStackConcurrentBagBlockingCollection

有一样东西似乎神秘地丢失了,那就是ConcurrentList<T>。我是不是必须自己写(或者从网上下载: )?

我是不是漏掉了什么明显的东西?

EN

回答 12

Stack Overflow用户

回答已采纳

发布于 2011-07-07 03:27:37

I gave it a try a while back (也叫:on GitHub)。我的实现有一些问题,我不会在这里讨论。让我告诉你,更重要的是,我学到了什么。

首先,你不可能得到一个无锁和线程安全的IList<T>的完整实现。特别是,随机插入和随机删除是不会起作用的,除非你也忘记了O(1)随机访问(也就是,除非你“作弊”,只是使用某种链表,让索引变得糟糕)。

我认为可能值得考虑的是IList<T>的一个线程安全的有限子集:特别是允许Add并按索引提供随机只读访问(但没有InsertRemoveAt等,也没有随机写访问)的子集。

这是my ConcurrentList implementation的目标。但当我在多线程场景中测试它的性能时,我发现简单地同步添加到 List<T> 的速度更快。基本上,添加到List<T>的速度已经很快了;所涉及的计算步骤的复杂性微不足道(递增索引并分配给数组中的元素;就是这样)。您将需要大量的并发写入才能看到这种情况下的任何类型的锁争用;即使这样,每次写入的平均性能仍将击败ConcurrentList<T>中更昂贵的无锁实现。

在相对较少的情况下,列表的内部数组需要调整自身的大小,您确实需要付出很小的代价。因此,我最终得出的结论是,这是唯一适合使用仅添加ConcurrentList<T>集合类型的场景:当您希望保证在每次调用时添加元素的开销较低时(因此,与分期的性能目标相反)。

它并不像你想象的那样有用。

票数 172
EN

Stack Overflow用户

发布于 2011-07-07 03:10:01

你会用ConcurrentList做什么?

线程世界中的随机访问容器的概念并不像它看起来那么有用。这句话

代码语言:javascript
运行
复制
  if (i < MyConcurrentList.Count)  
      x = MyConcurrentList[i]; 

作为一个整体,仍然不是线程安全的。

与其创建一个ConcurrentList,不如试着用现有的东西来构建解决方案。最常见的类是ConcurrentBag,尤其是BlockingCollection。

票数 41
EN

Stack Overflow用户

发布于 2014-05-03 23:52:53

尽管已经提供了很好的答案,但有时我只是想要一个线程安全的IList。没有什么先进或花哨的东西。在许多情况下,性能很重要,但有时这并不是一个问题。是的,没有像"TryGetValue“这样的方法总是会有挑战,但大多数情况下,我只是想要一些我可以列举的东西,而不需要担心在所有东西周围都放上锁。是的,有人可能会在我的实现中发现一些可能导致死锁或其他东西的“错误”(我想),但让我们诚实地说:当涉及到多线程时,如果你没有正确地编写你的代码,它无论如何都会死锁。考虑到这一点,我决定创建一个简单的ConcurrentList实现来满足这些基本需求。

对于它的价值:我做了一个基本的测试,将1000,000,000个项目添加到常规列表和ConcurrentList中,结果是:

列表完成时间: 7793毫秒。并发完成时间: 8064毫秒。

代码语言:javascript
运行
复制
public class ConcurrentList<T> : IList<T>, IDisposable
{
    #region Fields
    private readonly List<T> _list;
    private readonly ReaderWriterLockSlim _lock;
    #endregion

    #region Constructors
    public ConcurrentList()
    {
        this._lock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
        this._list = new List<T>();
    }

    public ConcurrentList(int capacity)
    {
        this._lock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
        this._list = new List<T>(capacity);
    }

    public ConcurrentList(IEnumerable<T> items)
    {
        this._lock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
        this._list = new List<T>(items);
    }
    #endregion

    #region Methods
    public void Add(T item)
    {
        try
        {
            this._lock.EnterWriteLock();
            this._list.Add(item);
        }
        finally
        {
            this._lock.ExitWriteLock();
        }
    }

    public void Insert(int index, T item)
    {
        try
        {
            this._lock.EnterWriteLock();
            this._list.Insert(index, item);
        }
        finally
        {
            this._lock.ExitWriteLock();
        }
    }

    public bool Remove(T item)
    {
        try
        {
            this._lock.EnterWriteLock();
            return this._list.Remove(item);
        }
        finally
        {
            this._lock.ExitWriteLock();
        }
    }

    public void RemoveAt(int index)
    {
        try
        {
            this._lock.EnterWriteLock();
            this._list.RemoveAt(index);
        }
        finally
        {
            this._lock.ExitWriteLock();
        }
    }

    public int IndexOf(T item)
    {
        try
        {
            this._lock.EnterReadLock();
            return this._list.IndexOf(item);
        }
        finally
        {
            this._lock.ExitReadLock();
        }
    }

    public void Clear()
    {
        try
        {
            this._lock.EnterWriteLock();
            this._list.Clear();
        }
        finally
        {
            this._lock.ExitWriteLock();
        }
    }

    public bool Contains(T item)
    {
        try
        {
            this._lock.EnterReadLock();
            return this._list.Contains(item);
        }
        finally
        {
            this._lock.ExitReadLock();
        }
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        try
        {
            this._lock.EnterReadLock();
            this._list.CopyTo(array, arrayIndex);
        }
        finally
        {
            this._lock.ExitReadLock();
        }
    }

    public IEnumerator<T> GetEnumerator()
    {
        return new ConcurrentEnumerator<T>(this._list, this._lock);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return new ConcurrentEnumerator<T>(this._list, this._lock);
    }

    ~ConcurrentList()
    {
        this.Dispose(false);
    }

    public void Dispose()
    {
        this.Dispose(true);
    }

    private void Dispose(bool disposing)
    {
        if (disposing)
            GC.SuppressFinalize(this);

        this._lock.Dispose();
    }
    #endregion

    #region Properties
    public T this[int index]
    {
        get
        {
            try
            {
                this._lock.EnterReadLock();
                return this._list[index];
            }
            finally
            {
                this._lock.ExitReadLock();
            }
        }
        set
        {
            try
            {
                this._lock.EnterWriteLock();
                this._list[index] = value;
            }
            finally
            {
                this._lock.ExitWriteLock();
            }
        }
    }

    public int Count
    {
        get
        {
            try
            {
                this._lock.EnterReadLock();
                return this._list.Count;
            }
            finally
            {
                this._lock.ExitReadLock();
            }
        }
    }

    public bool IsReadOnly
    {
        get { return false; }
    }
    #endregion
}

    public class ConcurrentEnumerator<T> : IEnumerator<T>
{
    #region Fields
    private readonly IEnumerator<T> _inner;
    private readonly ReaderWriterLockSlim _lock;
    #endregion

    #region Constructor
    public ConcurrentEnumerator(IEnumerable<T> inner, ReaderWriterLockSlim @lock)
    {
        this._lock = @lock;
        this._lock.EnterReadLock();
        this._inner = inner.GetEnumerator();
    }
    #endregion

    #region Methods
    public bool MoveNext()
    {
        return _inner.MoveNext();
    }

    public void Reset()
    {
        _inner.Reset();
    }

    public void Dispose()
    {
        this._lock.ExitReadLock();
    }
    #endregion

    #region Properties
    public T Current
    {
        get { return _inner.Current; }
    }

    object IEnumerator.Current
    {
        get { return _inner.Current; }
    }
    #endregion
}
票数 18
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6601611

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档