简体   繁体   English

了解Java的同步集合

[英]understanding java's synchronized collections

I'm reading the java official doc regarding wrappers implementation, which are static methods in Collections used to get synchronized collection, for example : List<Type> list = Collections.synchronizedList(new ArrayList<Type>()); 我正在阅读有关包装器实现的Java官方文档 ,这是Collections中用于获取同步集合的静态方法,例如: List<Type> list = Collections.synchronizedList(new ArrayList<Type>()); ... ...
the thing that I did not understand is the following (I quote from the java doc ) : 我不明白的是以下内容(我引用了Java doc):

A collection created in this fashion is every bit as thread-safe as a normally synchronized collection, such as a Vector. 以这种方式创建的集合与正常同步的集合(例如,Vector)一样,具有线程安全性 In the face of concurrent access, it is imperative that the user manually synchronize on the returned collection when iterating over it. 面对并发访问,当用户遍历返回的集合时,必须手动对其进行同步 The reason is that iteration is accomplished via multiple calls into the collection, which must be composed into a single atomic operation... 原因是迭代是通过对集合的多次调用来完成的,必须将其组成一个原子操作。

how it could be every bit as thread-safe an need to manually synchronize when iterating ?? 迭代时需要怎样手动同步才可能是线程安全的?

It is thread safe in the sense that each of it's individual methods are thread safe, but if you perform compound actions on the collection, then your code is at risk of concurrency issues. 从线程安全的角度来说,它是线程安全的,但是如果您对集合执行复合操作,则代码有并发问题的风险。

ex: 例如:

List<String> synchronizedList = Collections.synchronizedList(someList);
synchronizedList.add(whatever); // this is thread safe

the individual method add() is thread safe but if i perform the following: 单独的方法add()是线程安全的,但是如果我执行以下操作:

List<String> synchronizedList = Collections.synchronizedList(someList);
if(!synchronizedList.contains(whatever))
       synchronizedList.add(whatever); // this is not thread safe

the if-then-add operation is not thread safe because some other thread might have added whatever to the list after contains() check. if-then-add操作不是线程安全的,因为其他一些线程可能在contains()检查之后将whatever添加到了列表contains()

There is no contradiction here: collections returned from synchronizedXyz suffer the same shortcoming as synchronized collections available to you directly, namely the need to manually synchronize on iterating the collection. 这里没有矛盾:从返回集合synchronizedXyz直接遭受提供给你同样的缺点是同步集合,即需要在遍历集合手动同步。

The problem of external iteration cannot be solved by a better class design, because iterating a collection inherently requires making multiple calls to its methods ( see this Q&A for detailed explanation ). 外部迭代的问题无法通过更好的类设计来解决,因为迭代集合固有地需要对它的方法进行多次调用( 有关详细说明,请参见此Q&A )。

Note that starting with Java 1.8 you can iterate without additional synchronization using forEach method of your synchronized collection * . 请注意,从Java 1.8开始,您可以使用同步集合*的 forEach方法进行迭代,而无需进行其他同步。 This is thread-safe, and comes with additional benefits; 这是线程安全的,并具有其他好处。 see this Q&A for details . 有关详细信息,请参见此问答

The reason this is different from iterating externally is that forEach implementation inside the collection takes care of synchronizing the iteration for you. 与外部迭代不同的原因是,集合内部的forEach实现会为您同步迭代。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM