C# 列表的线程安全版本-实现
在阅读了大量关于堆栈溢出的文章之后,我认为我能够找到一个线程安全版本的List,它肯定达不到并发集合的级别,因为它使用了ReaderWriterLockSlim,但据我所知,它工作正常,与简单锁版本相比性能更好。您认为可以在当前实现中改进的任何内容。它仍然没有实现List的所有功能,因为我刚刚处理了IList 免责声明-我从堆栈溢出中得到了灵感,所以它肯定包含了来自不同帖子的部分 修改-修改代码以考虑某些场景,这些场景在上次通信中发布,如:C# 列表的线程安全版本-实现,c#,.net,multithreading,parallel-processing,task-parallel-library,C#,.net,Multithreading,Parallel Processing,Task Parallel Library,在阅读了大量关于堆栈溢出的文章之后,我认为我能够找到一个线程安全版本的List,它肯定达不到并发集合的级别,因为它使用了ReaderWriterLockSlim,但据我所知,它工作正常,与简单锁版本相比性能更好。您认为可以在当前实现中改进的任何内容。它仍然没有实现List的所有功能,因为我刚刚处理了IList 免责声明-我从堆栈溢出中得到了灵感,所以它肯定包含了来自不同帖子的部分 修改-修改代码以考虑某些场景,这些场景在上次通信中发布,如: if(list.count > 0) ret
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();
}
}
}
这种实现有点漏洞百出,因为即使每个原子操作(例如每个方法调用)都是线程安全的,但总体上还是容易出错的
来说明,考虑这种代码:
if(!myThreadSafeList.Contains(item))
myThreadSafeList.Add(item);
这两个操作是线程安全的,但总体上不是
正如trailmax在评论中建议的那样,您可以使用.Net Concurent集合
另一种选择是在Nuget上提供
这些是线程安全的,而且没有锁
Ps:如果你打算使用不可变的集合,尽管。。。使用方法在C中实现。为什么不只使用.Net并发集合?问题是什么?这个问题似乎与主题无关,因为它是关于CodeReview的。主要问题是没有使每个方法都是线程安全的,这很容易。它使包含多个方法调用的整个操作以一致的方式运行。@trailmax最近的是ConcurrentBag,它不是真正意义上的列表,因为它没有为数据提供有序索引方法。事实上,并提供另一个示例代码,如if list.Count>0 return list[0];完全同意,但我将告诉您一个场景,即使是并发集合和不可变列表也会失败。我的系统上有一个outlook客户端,我的手机上也配置了相同的邮件,因此我多次删除手机上的邮件,但它位于系统的outlook界面中,单击它会由于已知原因出现未知错误。与我的应用程序类似,是否有任何集合可用于此场景,事实上,此场景需要实时检查和更新接口,在当前情况下,我只需要包装上述异常case@MrinalKamboj这不是一个反例,这是关于同步访问您的邮件帐户,与并发收集无关。@Dirk请解释跨设备的同步访问Windows系统、Android手机,您将如何解决上述情况。要么它必须进行投票和更新,要么创建一个通知系统,但这两种方式都是昂贵的,我没有看到微软Outlook这样做,而安卓这样做是为了取缔Versa@MrinalKamboj并发集合或使集合访问线程安全是指单个进程内的并发访问。要在另一个进程中或甚至在另一个设备上更新数据,您需要推送或拉送方法,这两种方法都不是问题或答案的主题。