为什么List <T>不是线程安全的?
从以下网站:
http://crfdesign.net/programming/top-10-differences-between-java-and-c
不幸的是,
List<>
不是线程安全的(C#的ArrayList
和Java的Vector
是线程安全的)。 C#也有一个Hashtable
; 通用版本是:
是什么让List<T>
不是线程安全的? .NET框架工程师的实现问题? 或者generics不是线程安全的?
您确实需要对Java的Vectortypes的线程安全性进行分类。 Javas Vector可以安全地从多个线程使用,因为它使用方法上的同步。 国家将不会被损坏。
但是,Java的向量的有用性是有限的multithreading没有额外的同步。 例如,考虑从vector中读取元素的简单行为
Vector vector = getVector(); if ( vector.size() > 0 ) { object first = vector.get(0); }
这种方法不会破坏vector的状态,但也是不正确的。 在if语句和get()调用之间,没有任何东西阻止另一个线程在向量之间进行变异。 由于竞争条件,此代码最终可能会失败。
这种types的同步只是在方便的情况下才有用,而且肯定不便宜。 即使您不使用多个线程,也需要付出可观的同步价格。
.netselect不支付这个价格默认情况下只有有限的情况。 相反,它select了实现一个无锁的列表。 作者负责添加任何同步。 这更接近于C ++的“只为你使用的东西付费”
我最近写了一些关于使用集合的危险的文章,只有内部同步,比如Java的向量。
- 为什么线程安全的集合这么难?
- 一个可变的线程安全集合更可用的API
参考向量线程安全: http : //www.ibm.com/developerworks/java/library/j-jtp09263.html
为什么它是线程安全的? 并不是每个class级都是。 事实上,默认情况下,类不是线程安全的。
线程安全意味着修改列表的任何操作都需要与同时访问互锁。 即使是那些只能由单个线程使用的列表,这也是必要的。 这将是非常低效的。
这只是一个devise决定,实现不是线程安全的types。 这些集合为某些集合提供了接口ICollection
的属性SyncRoot
和Synchronized()
方法,用于显式同步数据types。
使用SyncRoot
lockingmultithreading环境中的对象。
lock (collection.SyncRoot) { DoSomething(collection); }
使用collection.Synchronized()
获取collection.Synchronized()
的线程安全包装器。
JaredPar提到的竞争条件可能性是依赖Vector的线程安全性的可怕后果。 这种情况会导致“每个星期二的应用程序都会出现一些奇怪的现象”,这些缺陷报告会让你疯狂。
在.NET 4中有很多真正的线程安全的集合,它们有一个有趣的副作用,它们允许枚举时对集合进行单线程修改 ,但是线程安全性有时会带来性能上的打击大的一个。
所以对于框架开发人员来说,合乎逻辑的事情是让95%的用户可能不会进行线程化,并依靠那些使用multithreading的用户来了解他们必须做些什么它安全。
为了真正的线程安全, List<>
和其他集合types需要是不可变的。 .NET 4.0的并行扩展出现在.NET 4.0中,我们将看到最常用集合的线程安全版本。 Jon Skeet谈到了这一点。
使用SynchronizedCollection它也提供了一个使用共享同步的构造函数参数:)