.net 为什么 List<T> 不是线程安全的?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/703990/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 12:27:00  来源:igfitidea点击:

Why is List<T> not thread-safe?

.netgenericsthread-safety

提问by Hao

From the following site:

来自以下网站:

http://crfdesign.net/programming/top-10-differences-between-java-and-c

http://crfdesign.net/programming/top-10-differences-between-java-and-c

Unfortunately, List<>is not thread-safe (C#'s ArrayListand Java's Vectorare thread-safe). C# also has a Hashtable; the generic version is:

不幸的是,List<>它不是线程安全的(C#ArrayList和 Java Vector是线程安全的)。C# 也有一个Hashtable; 通用版本是:

What makes List<T>not thread-safe? Is it implementation problem on .NET framework engineer's part? Or are generics not thread-safe?

是什么让List<T>线程不安全?它是 .NET 框架工程师的实现问题吗?或者泛型不是线程安全的?

回答by JaredPar

You really need to classify Java's Vector's type of thread safety. Javas Vector is safe to be used from multiple threads because it uses synchronization on the methods. State will not be corrupted.

您确实需要对 Java 的 Vector 类型的线程安全进行分类。Javas Vector 可以安全地从多个线程使用,因为它在方法上使用同步。状态不会被破坏。

However, Java's vector's usefulness is limited from multiple threads without additional synchronization. For example, consider the simple act of reading an element from a vector

然而,Java 的向量的用处仅限于多线程,没有额外的同步。例如,考虑从向量中读取元素的简单行为

Vector vector = getVector();
if ( vector.size() > 0 ) { 
  object first = vector.get(0);
}

This method will not corrupt the state of the vector, but it also is not correct. There is nothing stopping another thread from mutating the vector in between the if statement an the get() call. This code can and willeventually fail because of a race condition.

这种方法不会破坏向量的状态,但它也是不正确的。没有什么可以阻止另一个线程在 if 语句和 get() 调用之间改变向量。此代码可以和最终失败的原因的竞争条件。

This type of synchronization is only useful in a handfull of scenarios and it is certainly not cheap. You pay a noticable price for synchronization even if you don't use multiple threads.

这种类型的同步只在少数场景中有用,而且肯定不便宜。即使您不使用多线程,您也要为同步付出可观的代价。

.Net chose not to pay this price by default for a scenario of only limited usefulness. Instead it chose to implement a lock free List. Authors are responsible for adding any synchronization. It's closer to C++'s model of "pay only for what you use"

.Net 选择在默认情况下不支付这个价格,用于仅有限用处的场景。相反,它选择实现一个无锁列表。作者负责添加任何同步。它更接近 C++ 的“按使用量付费”的模型

I recently wrote a couple of articles on the dangers of using collections with only internal synchronization such as Java's vector.

我最近写了几篇关于使用仅具有内部同步的集合(例如 Java 的向量)的危险的文章。

Reference Vector thread safety: http://www.ibm.com/developerworks/java/library/j-jtp09263.html

参考向量线程安全:http: //www.ibm.com/developerworks/java/library/j-jtp09263.html

回答by John Saunders

Why wouldit be thread-safe? Not every class is. In fact, by default, classes are notthread-safe.

为什么它是线程安全的?不是每个班级都是。事实上,默认情况下,类不是线程安全的。

Being thread-safe would mean that any operation modifying the list would need to be interlocked against simultaneous access. This would be necessary even for those lists that will only ever be used by a single thread. That would be very inefficient.

线程安全意味着任何修改列表的操作都需要互锁以防止同时访问。即使对于那些只能由单个线程使用的列表,这也是必要的。那将是非常低效的。

回答by Daniel Brückner

It is simply a design decision to implement the types not thread safe. The collections provide the property SyncRootof the interface ICollectionand the Synchronized()method on some collections for explicitly synchronizing the data types.

实现非线程安全的类型只是一个设计决策。集合提供SyncRoot接口的属性ICollectionSynchronized()一些集合上用于显式同步数据类型的方法。

Use SyncRootto lock an object in multithreaded environments.

用于SyncRoot在多线程环境中锁定对象。

lock (collection.SyncRoot)
{
   DoSomething(collection);
}

Use collection.Synchronized()to obtain a thread-safe wrapper for the collection.

使用collection.Synchronized()以获得集合的线程安全的包装。

回答by Abhijeet Patel

For true thread safety, List<>and other collection types would need to be immutable. With the parallel extensions to .NET coming out in .NET 4.0 we'll be seeing thread safe versions of the most commonly used collections. Jon Skeettouches on some of this.

为了真正的线程安全,List<>其他集合类型需要是不可变的。随着 .NET 4.0 中对 .NET 的并行扩展,我们将看到最常用集合的线程安全版本。 Jon Skeet 谈到了其中的一些内容。

回答by Ragoczy

The race-condition possibility JaredPar mentions is the scary consequence of relying on Vector's supposed thread-safety. It's the sort of thing that results in the "every ninth Tuesday the app does something weird"-sort of defect report that will drive you insane.

JaredPar 提到的竞争条件可能性是依赖 Vector 假定的线程安全性的可怕后果。正是这种事情导致“应用程序每个第九个星期二都会做一些奇怪的事情”——一种会让你发疯的缺陷报告。

There are a number of truly thread-safe collections coming in .Net 4, with an interesting side-effect that they allow single-threaded modification of the collection while enumerating, but there's a performance hitthat comes with thread-safety, sometimes a pretty big one.

.Net 4中有许多真正线程安全的集合,它们有一个有趣的副作用,即它们允许在枚举时对集合进行单线程修改,但是线程安全会带来性能上的影响,有时甚至很漂亮大的一个。

So the logical thing for a framework developer to do is keep the class as performant as possible for the 95% of users who probably won't be doing threading and rely on those who do multi-thread to know what they have to do to keep it safe.

因此,框架开发人员要做的合乎逻辑的事情是让 95% 的用户尽可能保持类的性能,这些用户可能不会进行线程处理并依赖于那些进行多线程操作的用户知道他们必须做什么才能保持它安全。

回答by mo.

use SynchronizedCollection it also provides a Constructor-Parameter to use a shared sync :)

使用 SynchronizedCollection 它还提供了一个构造函数参数来使用共享同步:)