线程安全版本的List<;T>;-实施

本文关键字:gt 实施 安全 lt List 线程 版本 | 更新日期: 2023-09-27 18:21:14

在阅读了大量关于Stack Overflow的帖子后,我认为我能够想出一个线程安全的List版本,它肯定达不到并发集合的水平,因为它使用了ReaderWriterLockSlim,但据我所知,它按预期工作,与简单的锁版本相比性能更好。您可能认为在当前实现中可以改进的任何内容。它仍然没有实现List的所有功能,因为我刚刚处理了IList

免责声明-我从Stack Overflow中得到了这个想法,所以它肯定包含了来自各种帖子的点点滴滴

修改-修改代码以处理某些场景,这些场景在上次通信中发布,如:

if(list.count > 0)
  return list[0]

没有理由将此标记为非主题

线程安全实现

using System.Collections.Generic;
using System.Threading;

/// <summary>
/// Thread safe version of the List using 
/// </summary>
/// <typeparam name="T"></typeparam>
public class ThreadSafeListWithRWLock<T> : IList<T>
{
    private List<T> internalList;
    private readonly ReaderWriterLockSlim rwLockList;
    public ThreadSafeListWithRWLock()
    {
        internalList = new List<T>();
        rwLockList = new ReaderWriterLockSlim();
    }
    // Other Elements of IList implementation
    public IEnumerator<T> GetEnumerator()
    {
        return Clone().GetEnumerator();
    }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return Clone().GetEnumerator();
    }
    public List<T> Clone()
    {
        List<T> clonedList = new List<T>();
        rwLockList.EnterReadLock();
        internalList.ForEach(element => { clonedList.Add(element); });
        rwLockList.ExitReadLock();
        return (clonedList);
    }
    public void Add(T item)
    {
        rwLockList.EnterWriteLock();
        internalList.Add(item);
        rwLockList.ExitWriteLock();
    }
    public bool Remove(T item)
    {
        bool isRemoved;
        rwLockList.EnterWriteLock();
        isRemoved = internalList.Remove(item);
        rwLockList.ExitWriteLock();
        return (isRemoved);
    }
    public void Clear()
    {
        rwLockList.EnterWriteLock();
        internalList.Clear();
        rwLockList.ExitWriteLock();
    }
    public bool Contains(T item)
    {
        bool containsItem;
        rwLockList.EnterReadLock();
        containsItem = internalList.Contains(item);
        rwLockList.ExitReadLock();
        return (containsItem);
    }
    public void CopyTo(T[] array, int arrayIndex)
    {
        rwLockList.EnterReadLock();
        internalList.CopyTo(array,arrayIndex);
        rwLockList.ExitReadLock();
    }
    public int Count
    {
        get
        {
            int count;
            rwLockList.EnterReadLock();
            count = internalList.Count;
            rwLockList.ExitReadLock();
            return (count);
        }
    }
    public bool IsReadOnly
    {
        get { return false; }
    }
    public int IndexOf(T item)
    {
        int itemIndex;
        rwLockList.EnterReadLock();
        itemIndex = internalList.IndexOf(item);
        rwLockList.ExitReadLock();
        return (itemIndex);
    }
    public void Insert(int index, T item)
    {
      rwLockList.EnterWriteLock();
      if (index <= internalList.Count - 1)
        internalList.Insert(index,item);
      rwLockList.ExitWriteLock();
    }
    public void RemoveAt(int index)
    {
       rwLockList.EnterWriteLock();
       if (index <= internalList.Count - 1)
        internalList.RemoveAt(index);
       rwLockList.ExitWriteLock();
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="index"></param>
    /// <returns></returns>
    public T this[int index] 
    {
        get
        {
            T returnItem = default(T);
           rwLockList.EnterReadLock();
           if (index <= internalList.Count - 1)
               returnItem = internalList[index];              
           rwLockList.ExitReadLock();
            return (returnItem);
        }
        set
        {
            rwLockList.EnterWriteLock();
            if (index <= internalList.Count - 1)
                internalList[index] = value;
            rwLockList.ExitWriteLock();
        }
    }
}

线程安全版本的List<;T>;-实施

这种实现有点泄漏,因为即使每个原子操作(例如每个方法调用)都是线程安全的,但总体上还是容易出错。

为了说明这一点,考虑一下这种代码:

if(!myThreadSafeList.Contains(item))
       myThreadSafeList.Add(item);

这两个操作是线程安全的,但总体上不是。

正如trailmax在评论中建议的那样,您可以使用.Net conccurent集合。

另一种选择是使用Nuget上提供的Microsoft不可变集合。

这些是线程安全的,而且,无锁!

Ps:如果你打算使用不可变的集合,请学习一些关于比较和交换循环的知识。。。使用InterlockedCompareExchange方法在C#中实现。