简体   繁体   English

存储在线程安全的集合中的对象是否安全?

[英]Are objects stored in thread safe collection thread safe?

Are the objects stored in a thread safe collection (like CopyOnWriteArrayList) thread safe? 存储在线程安全集合(如CopyOnWriteArrayList)中的对象是否安全? Let us say that the objects stored are mutable (not thread safe) then the fact that the collection (here CopyOnWriteArrayList) is thread safe provide any guarantee towards the thread safety of the reference stored in it? 让我们说存储的对象是可变的(不是线程安全的),那么集合(在这里,CopyOnWriteArrayList)是线程安全的事实为存储在其中的引用的线程安全提供了保证吗?

No, the objects are not thread-safe; 不,对象不是线程安全的; if two threads change a mutable object that they retrieved from a CopyOnWriteArrayList then they'll cause a data race. 如果两个线程更改了从CopyOnWriteArrayList检索的可变对象,则将导致数据争用。

If a collection is thread-safe then this means that two threads can add/remove objects from the collection without corrupting it (for example, an ArrayList is not thread-safe, so if two threads each try to add an object to the collection then one or both objects may be lost), however the objects in the collection will still need to be synchronized to make them thread-safe. 如果集合是线程安全的,则意味着两个线程可以在不破坏集合的情况下从集合中添加/删除对象(例如,ArrayList不是线程安全的,因此,如果两个线程各自尝试将对象添加到集合中,则一个或两个对象可能会丢失),但是仍然需要同步集合中的对象以使它们成为线程安全的。

There are some guarantees, usually a thread safe storage is analogous to volatile variables in terms of memory effect. 有一些保证,就内存效果而言,通常线程安全存储类似于易失性变量。

volatile Foo var;              final Vector<Foo> vars = new Vector<>()

// thread 1                    // thread 1
foo.bar = bar;  [1]            foo.bar = bar;         [1]
var = foo;                     vars.set(0, foo);

// thread 2                    // thread 2
bar = foo.bar;  [2]            bar = vars.get(0).bar; [2]

//read[2] sees write[1]        // read[2] sees write[1]

Basically, writes before insertion should be visible to reads after retrieval. 基本上,插入之前的写入对于检索之后的读取应该是可见的。

The only thread-safe guarantee provided is that the objects will be “safely published”. 提供的唯一线程安全保证是对象将被“安全发布”。 That is, they will become visible at once for all threads (this includes the reference to the object and its internal state). 也就是说,它们将立即对所有线程可见(这包括对对象及其内部状态的引用)。

Example: if thread A writes X, and thread B reads, B is guarantee to see X as A left it. 示例:如果线程A写入X,而线程B读取,则B保证看到X像A一样离开了X。 In other words, the read and write operations are consistent with the order in which they happen. 换句话说,读和写操作与其发生的顺序一致。

There are other ways to accomplish the same thing like using final , or volatile , or AtomicReference , or a lock (this is what the thread-safe collections are doing), or a static initializer. 还有其他方法可以完成同一件事,例如使用finalvolatileAtomicReference或锁(线程安全集合正在执行的操作)或静态初始化器。 See the book “Java Concurrency in Practice” for details. 有关详细信息,请参见《实践中的Java并发》一书。

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

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