我有System.Collections.Generic.SynchronizedCollection共享集合。我们的代码使用.Net 4.0任务库跨越线程并将同步的集合传递给线程。到目前为止,线程并没有向集合中添加或删除项目。但是需要其中一个线程的新需求必须从集合中删除项目,而另一个线程只读取集合。在从集合中删除项目之前是否需要添加锁定?如果是这样,读者线程是否是线程安全的?或建议最好的方式来获得线程安全?同步收集线程安全
同步收集线程安全
回答
是,SynchronizedCollection会做锁定你。
如果您有多个读者和只有一个作家,你可能想看看使用ReaderWriterLock,而不是SynchronizedCollection。
另外,如果你是净4+然后看看System.Collections.Concurrent
。这些类比SynchronizedCollection有更好的性能。
不,它不完全是线程安全的。尝试在一个简单的控制台的应用程序下面,看看它是如何与一个异常崩溃:
var collection = new SynchronizedCollection<int>();
var n = 0;
Task.Run(
() =>
{
while (true)
{
collection.Add(n++);
Thread.Sleep(5);
}
});
Task.Run(
() =>
{
while (true)
{
Console.WriteLine("Elements in collection: " + collection.Count);
var x = 0;
if (collection.Count % 100 == 0)
{
foreach (var i in collection)
{
Console.WriteLine("They are: " + i);
x++;
if (x == 100)
{
break;
}
}
}
}
});
Console.ReadKey();
请注意,如果您有ConcurrentBag更换SynchronizedCollection,你会得到线程安全:
var collection = new ConcurrentBag<int>();
SynchronizedCollection在此应用程序中根本不是线程安全的。改用Concurrent Collections。
亚历山大已经指出SynchronizedCollection
对于这种情况不是线程安全的。 SynchronizedCollection
实际上包装了一个普通的通用列表,并且只是将每个调用委托给基础列表,并且围绕该调用发出锁。这也在GetEnumerator
中完成。因此,枚举器的获取是同步的,但不是实际的枚举。
var collection = new SynchronizedCollection<string>();
collection.Add("Test1");
collection.Add("Test2");
collection.Add("Test3");
collection.Add("Test4");
var enumerator = collection.GetEnumerator();
enumerator.MoveNext();
collection.Add("Test5");
//The next call will throw a InvalidOperationException ("Collection was modified")
enumerator.MoveNext();
当使用foreach时,将以这种方式调用枚举器。因此,在通过此数组枚举之前添加ToArray()
将不起作用,因为这将首先枚举到此数组中。 当你在你的foreach中做什么时,这个枚举可能会更快,所以它可以减少获得并发问题的可能性。正如理查德指出的那样:为了真正的线程安全,请去System.Collections.Concurrent
类。
然而,在调用'ToArray'之前,您可以使用集合的'SyncRoot'属性。 –
- 1. 线程安全java - 收集/列表
- 2. 线程安全分类收集
- 3. 安全地同步COM线程
- 4. 为线程安全同步NSMutableArray?
- 5. 使用同步的Java多线程不是线程安全的
- 6. 线程同步是否意味着线程安全?
- 7. 收集合同和线程
- 8. 链接线程安全集合线程安全吗?
- 9. 异步,线程安全的集合实现INotifyCollectionChanged
- 10. 同步vs线程安全集合vs原子包装类vs锁
- 11. java线程安全:线程安全吗?
- 12. 多核系统中的最终收集线程是否安全?
- 13. Scala for Akka Actors的线程安全收集
- 14. 一个内部另一个并发收集:是线程安全
- 15. 什么线程安全的收集适合这种情况?
- 16. 线程安全的收集没有订单,也没有重复
- 17. 线程安全异步字节队列
- 18. 使RxJava异步任务线程安全
- 19. 异步文件IO线程安全吗?
- 20. 我的收藏线程安全吗?
- 21. 使您的收藏线程安全?
- 22. 线程安全VS异步信号安全
- 23. Websocket发送/接收线程安全(去例行安全)?
- 24. 同步访问非易失性字段线程安全吗?
- 25. 调用Javascript方法是线程安全还是同步?
- 26. 这是静态方法线程安全或需要同步
- 27. 是java中整数线程安全读取的不同步吗?
- 28. 线程安全的引用类型,而无需使用同步
- 29. 这个同步对象实现线程安全吗?
- 30. winsock 2.同步发送的线程安全。 tcp
如果您使用的是SynchronizedCollection,它应该已经被提供在该添加/从集合中删除操作的适当的锁定。 – Joe
这是否也支持在从另一个线程中删除项目时枚举另一个线程中的集合?我是否需要锁定枚举部分? – Amzath
现有的“SynchronizedCollection”的全部重点是为所有操作提供线程安全的集合(它通过锁定所有操作)。如果您使用的是ICollection,那么您可能需要自行锁定。请注意,如果您的目标是4.0框架或更高版本,则可能会看到使用System.Collections.Concurrent时的性能改进...... –
Joe