我有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