创建使用读写器锁线程安全名单线程、读写器、名单、安全

2023-09-04 01:12:47 作者:精神病院vip患者

完全编辑的早期版本,下面的实现可能是线程安全的List实现。我只需要知道它是否能够真正线程安全与否,我知道性能方面还是会有问题。目前的版本是用ReaderWriterLockSlim,我必须使用锁另一种实现方式,做同样的工作。

使用System.Collections.Generic; 使用的System.Threading;

  ///<总结>
///线程安全使用ReaderWriterLockSlim列表的版本
///< /总结>
///< typeparam名=T>< / typeparam>
公共类ThreadSafeListWithRWLock< T> :IList的< T>
{
    这将在一个线程安全的方式访问//内部私有列表
    私人列表< T> internalList;

    // ReaderWriterLockSlim对象采取多个读者和作者之间的保健线程安全接取的
    私人只读ReaderWriterLockSlim rwLockList;

    ///<总结>
    ///公共构造函数初始化变量code
    ///< /总结>
    公共ThreadSafeListWithRWLock()
    {
        internalList =新的名单,其中,T>();

        rwLockList =新ReaderWriterLockSlim();
    }

    ///<总结>
    ///获取枚举线程安全列表
    ///< /总结>
    ///<返回>< /回报>
    公众的IEnumerator< T>的GetEnumerator()
    {
        返回克隆()的GetEnumerator()。
    }

    ///<总结>
    /// System.Collections.IEnumerable.GetEnumerator实施得到的IEnumerator类型
    ///< /总结>
    ///<返回>< /回报>
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        返回克隆()的GetEnumerator()。
    }

    ///<总结>
    ///克隆方法的线程安全列表的内存拷贝创建
    ///< /总结>
    ///<返回>< /回报>
    公开名单< T>克隆()
    {
        名单< T> clonedList =新的名单,其中,T>();

        rwLockList.EnterReadLock();

        internalList.ForEach(元=> {clonedList.Add(元);});

        rwLockList.ExitReadLock();

        返程(clonedList);
    }

    ///<总结>
    ///添加一个项目主题安全列表
    ///< /总结>
    ///< PARAM NAME =项>< /参数>
    公共无效添加(T项)
    {
        rwLockList.EnterWriteLock();

        internalList.Add(项目);

        rwLockList.ExitWriteLock();
    }

    ///<总结>
    ///从线程安全的列表中删除一个项目
    ///< /总结>
    ///< PARAM NAME =项>< /参数>
    ///<返回>< /回报>
    公共BOOL删除(T项目)
    {
        布尔isRemoved;

        rwLockList.EnterWriteLock();

        isRemoved = internalList.Remove(项目);

        rwLockList.ExitWriteLock();

        返回(isRemoved);
    }

    ///<总结>
    螺纹安全列表///清除所有元素
    ///< /总结>
    公共无效清除()
    {
        rwLockList.EnterWriteLock();

        internalList.Clear();

        rwLockList.ExitWriteLock();
    }

    ///<总结>
    ///包含了线程安全列表中的项目
    ///< /总结>
    ///< PARAM NAME =项>< /参数>
    ///<返回>< /回报>
    公共BOOL包含(T项)
    {
        布尔containsItem;

        rwLockList.EnterReadLock();

        containsItem = internalList.Contains(项目);

        rwLockList.ExitReadLock();

        返回(containsItem);
    }

    ///<总结>
    线程安全列表中的阿雷///元素复制到兼容的数组,从指定的索引
    ///< /总结>
    ///< PARAM NAME =阵列>< /参数>
    ///< PARAM NAME =arrayIndex>< /参数>
    公共无效CopyTo从(T []数组,INT arrayIndex)
    {
        rwLockList.EnterReadLock();

        internalList.CopyTo(阵列,arrayIndex);

        rwLockList.ExitReadLock();
    }

    ///<总结>
    ///伯爵在一个线程安全的列表元素
    ///< /总结>
    公众诠释计数
    {
        得到
        {
            诠释计数;

            rwLockList.EnterReadLock();

            数= internalList.Count;

            rwLockList.ExitReadLock();

            返回(计数);
        }
    }

    ///<总结>
    ///检查是否线程安全名单为只读
    ///< /总结>
    公共BOOL的IsReadOnly
    {
        获得{返回false; }
    }

    ///<总结>
    在线程安全列表///一个项目的索引
    ///< /总结>
    ///< PARAM NAME =项>< /参数>
    ///<返回>< /回报>
    公众诠释的IndexOf(T项)
    {
        INT的ItemIndex;

        rwLockList.EnterReadLock();

        的ItemIndex = internalList.IndexOf(项目);

        rwLockList.ExitReadLock();

        返回(的ItemIndex);
    }

    ///<总结>
    ///插入一个项目在一个线程安全列表中指定索引处
    ///< /总结>
    ///< PARAM NAME =指数>< /参数>
    ///< PARAM NAME =项>< /参数>
    公共无效插入(INT指数,T项)
    {
      rwLockList.EnterWriteLock();

      如果(指数< = internalList.Count  -  1安培;&安培;索引> = 0)
        internalList.Insert(索引项);

      rwLockList.ExitWriteLock();
    }

    ///<总结>
    ///指定索引在线程安全的列表中删除一个项目
    ///< /总结>
    ///< PARAM NAME =指数>< /参数>
    公共无效RemoveAt(INT指数)
    {
       rwLockList.EnterWriteLock();

       如果(指数< = internalList.Count  -  1安培;&安培;索引> = 0)
        internalList.RemoveAt(指数);

       rwLockList.ExitWriteLock();
    }

    ///<总结>
    ///索引器线程安全名单
    ///< /总结>
    ///< PARAM NAME =指数>< /参数>
    ///<返回>< /回报>
    公共牛逼这个[INT指数]
    {
        得到
        {
            牛逼returnItem =默认(T);

           rwLockList.EnterReadLock();

           如果(指数< = internalList.Count  -  1安培;&安培;索引> = 0)
               returnItem = internalList [指数]

           rwLockList.ExitReadLock();

            返程(returnItem);
        }
        组
        {
            rwLockList.EnterWriteLock();

            如果(指数< = internalList.Count  -  1安培;&安培;索引> = 0)
                internalList [指数] =值;

            rwLockList.ExitWriteLock();
        }
    }
}
 

解决方案

实现自定义名单,其中,T> ,它封装了线程安全是很不值得的努力。你可能最好关闭只是用锁定每当你访问名单,其中,T>

但在性能密集型产业做回我自己有过情况下,这将成为一个瓶颈。其主要缺点锁定是上下文切换是,相对而言,极其昂贵无论是在挂钟时间和CPU周期的可能性。

解决这个问题的最好方法是使用不变性。让所有的读者访问使用互锁操作,它与一个新的实例来替换不可变列表和作家更新。这是一个无锁的设计,使阅读免费的同步,并写入无锁(除上下文切换)。

我要强调的是,在几乎所有情况下,这是矫枉过正,我根本不会考虑走这条路,除非你是积极的,你需要和你了解的弊端。一对夫妇的明显的是读者获取点在时间快照和浪费内存创建副本。

ImmutableList 从的 Microsoft.Bcl.Immutable 也值得一看。这是完全线程安全的。

多线程 03 NSThread

Completely editing the earlier version, Can the following implementation be the Thread Safe List implementation. I just need to know whether it would truly thread safe or not, I know performance wise there would still be issues. Currently version is using ReaderWriterLockSlim, I have another implementation using the Lock, doing the same job

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

/// <summary>
/// Thread safe version of the List using ReaderWriterLockSlim 
/// </summary>
/// <typeparam name="T"></typeparam>
public class ThreadSafeListWithRWLock<T> : IList<T>
{
    // Internal private list which would be accessed in a thread safe manner
    private List<T> internalList;

    // ReaderWriterLockSlim object to take care of thread safe acess between multiple readers and writers
    private readonly ReaderWriterLockSlim rwLockList;

    /// <summary>
    /// Public constructor with variable initialization code
    /// </summary>
    public ThreadSafeListWithRWLock()
    {
        internalList = new List<T>();

        rwLockList = new ReaderWriterLockSlim();
    }

    /// <summary>
    /// Get the Enumerator to the Thread safe list
    /// </summary>
    /// <returns></returns>
    public IEnumerator<T> GetEnumerator()
    {
        return Clone().GetEnumerator();
    }

    /// <summary>
    /// System.Collections.IEnumerable.GetEnumerator implementation to get the IEnumerator type
    /// </summary>
    /// <returns></returns>
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return Clone().GetEnumerator();
    }

    /// <summary>
    /// Clone method to create an in memory copy of the Thread safe list
    /// </summary>
    /// <returns></returns>
    public List<T> Clone()
    {
        List<T> clonedList = new List<T>();

        rwLockList.EnterReadLock();

        internalList.ForEach(element => { clonedList.Add(element); });            

        rwLockList.ExitReadLock();

        return (clonedList);
    }

    /// <summary>
    /// Add an item to Thread safe list
    /// </summary>
    /// <param name="item"></param>
    public void Add(T item)
    {
        rwLockList.EnterWriteLock();

        internalList.Add(item);

        rwLockList.ExitWriteLock();
    }

    /// <summary>
    /// Remove an item from Thread safe list
    /// </summary>
    /// <param name="item"></param>
    /// <returns></returns>
    public bool Remove(T item)
    {
        bool isRemoved;

        rwLockList.EnterWriteLock();

        isRemoved = internalList.Remove(item);

        rwLockList.ExitWriteLock();

        return (isRemoved);
    }

    /// <summary>
    /// Clear all elements of Thread safe list
    /// </summary>
    public void Clear()
    {
        rwLockList.EnterWriteLock();

        internalList.Clear();

        rwLockList.ExitWriteLock();
    }

    /// <summary>
    /// Contains an item in the Thread safe list
    /// </summary>
    /// <param name="item"></param>
    /// <returns></returns>
    public bool Contains(T item)
    {
        bool containsItem;

        rwLockList.EnterReadLock();

        containsItem = internalList.Contains(item);

        rwLockList.ExitReadLock();

        return (containsItem);
    }

    /// <summary>
    /// Copy elements of the Thread safe list to a compatible array from specified index in the aray
    /// </summary>
    /// <param name="array"></param>
    /// <param name="arrayIndex"></param>
    public void CopyTo(T[] array, int arrayIndex)
    {
        rwLockList.EnterReadLock();

        internalList.CopyTo(array,arrayIndex);

        rwLockList.ExitReadLock();
    }

    /// <summary>
    /// Count elements in a Thread safe list
    /// </summary>
    public int Count
    {
        get
        {
            int count;

            rwLockList.EnterReadLock();

            count = internalList.Count;

            rwLockList.ExitReadLock();

            return (count);
        }
    }

    /// <summary>
    /// Check whether Thread safe list is read only
    /// </summary>
    public bool IsReadOnly
    {
        get { return false; }
    }

    /// <summary>
    /// Index of an item in the Thread safe list
    /// </summary>
    /// <param name="item"></param>
    /// <returns></returns>
    public int IndexOf(T item)
    {
        int itemIndex;

        rwLockList.EnterReadLock();

        itemIndex = internalList.IndexOf(item);

        rwLockList.ExitReadLock();

        return (itemIndex);
    }

    /// <summary>
    /// Insert an item at a specified index in a Thread safe list
    /// </summary>
    /// <param name="index"></param>
    /// <param name="item"></param>
    public void Insert(int index, T item)
    {
      rwLockList.EnterWriteLock();

      if (index <= internalList.Count - 1 && index >= 0)
        internalList.Insert(index,item);

      rwLockList.ExitWriteLock();
    }

    /// <summary>
    /// Remove an item at a specified index in Thread safe list
    /// </summary>
    /// <param name="index"></param>
    public void RemoveAt(int index)
    {
       rwLockList.EnterWriteLock();

       if (index <= internalList.Count - 1 && index >= 0)
        internalList.RemoveAt(index);

       rwLockList.ExitWriteLock();
    }

    /// <summary>
    /// Indexer for the Thread safe list
    /// </summary>
    /// <param name="index"></param>
    /// <returns></returns>
    public T this[int index] 
    {
        get
        {
            T returnItem = default(T);

           rwLockList.EnterReadLock();

           if (index <= internalList.Count - 1 && index >= 0)
               returnItem = internalList[index];              

           rwLockList.ExitReadLock();

            return (returnItem);
        }
        set
        {
            rwLockList.EnterWriteLock();

            if (index <= internalList.Count - 1 && index >= 0)
                internalList[index] = value;

            rwLockList.ExitWriteLock();
        }
    }
}

解决方案

Implementing a custom List<T> that encapsulates thread-safety is rarely worth the effort. You're likely best off just using lock whenever you access the List<T>.

But being in a performance intensive industry myself there have been cases where this becomes a bottleneck. The main drawback to lock is the possibility of context switching which is, relatively speaking, extremely expensive both in wall clock time and CPU cycles.

The best way around this is using immutability. Have all readers access an immutable list and writers "update" it using Interlocked operations to replace it with a new instance. This is a lock-free design that makes reads free of synchronization and writes lock-free (eliminates context switching).

I will stress that in almost all cases this is overkill and I wouldn't even consider going down this path unless you're positive you need to and you understand the drawbacks. A couple of the obvious ones are readers getting point-in-time snapshots and wasting memory creating copies.

ImmutableList from Microsoft.Bcl.Immutable is also worth a look. It's entirely thread-safe.