44

从以下网站:

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

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

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

4

6 回答 6

69

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

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

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

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

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

.Net 选择默认不支付这个价格,因为它的用处有限。相反,它选择实现一个无锁列表。作者负责添加任何同步。它更接近 C++ 的“只为你使用的东西付费”的模型

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

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

于 2009-04-01T03:55:54.133 回答
21

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

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

于 2009-04-01T03:54:55.400 回答
9

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

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

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

用于collection.Synchronized()获取集合的线程安全包装器。

于 2009-04-01T03:58:11.397 回答
2

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

于 2009-04-01T05:58:49.783 回答
2

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

.Net 4中有许多真正线程安全的集合,具有一个有趣的副作用,即它们允许在枚举时对集合进行单线程修改,但是线程安全带来了性能损失,有时甚至是相当不错的大的一个。

因此,对于框架开发人员来说,合乎逻辑的事情是让 95% 的用户尽可能保持类的性能,这些用户可能不会使用线程,并依赖那些使用多线程的用户来了解他们必须做些什么来保持它安全。

于 2009-04-03T18:18:12.433 回答
0

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

于 2010-01-29T12:39:48.160 回答