存储在线程安全集合(如CopyOnWriteArrayList)中的对象是否安全?让我们说存储的对象是可变的(不是线程安全的)然后集合(这里是CopyOnWriteArrayList)是线程安全的事实提供了对存储在其中的引用的线程安全性的任何保证吗?
答案 0 :(得分:5)
不,对象不是线程安全的;如果两个线程更改了从CopyOnWriteArrayList检索到的可变对象,那么它们将导致数据竞争。
如果集合是线程安全的,那么这意味着两个线程可以从集合中添加/删除对象而不会破坏它(例如,ArrayList不是线程安全的,所以如果两个线程都试图添加一个对象然后集合中的对象仍然需要同步以使它们成为线程安全的。
答案 1 :(得分:2)
有一些保证,通常线程安全存储在内存效应方面类似于volatile变量。
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]
基本上,插入前的写入对于检索后的读取应该是可见的。
答案 2 :(得分:1)
唯一提供的线程安全保证是对象将“安全发布”。也就是说,它们将立即对所有线程可见(这包括对对象及其内部状态的引用)。
示例:如果线程A写入X,而线程B读取,则B保证将X视为A离开它。换句话说,读写操作与它们发生的顺序一致。
还有其他方法可以实现相同的功能,例如使用final
,volatile
或AtomicReference
,或锁定(这是线程安全的集合正在做的事情),或静态初始化程序。有关详细信息,请参阅“Java Concurrency in Practice”一书。