0

存储在线程安全集合(如 CopyOnWriteArrayList)中的对象是否线程安全?假设存储的对象是可变的(不是线程安全的),那么集合(此处为 CopyOnWriteArrayList)是线程安全的这一事实为存储在其中的引用的线程安全性提供了任何保证吗?

4

3 回答 3

5

不,对象不是线程安全的;如果两个线程更改了它们从 CopyOnWriteArrayList 检索到的可变对象,那么它们将导致数据竞争。

如果一个集合是线程安全的,那么这意味着两个线程可以从集合中添加/删除对象而不会破坏它(例如,一个 ArrayList 不是线程安全的,所以如果两个线程都尝试将一个对象添加到集合中,那么一个或两个对象可能会丢失),但是集合中的对象仍需要同步以使其成为线程安全的。

于 2013-04-26T02:27:57.413 回答
2

有一些保证,通常线程安全存储在记忆效应方面类似于易失性变量。

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]

基本上,插入前的写入应该对检索后的读取可见。

于 2013-04-26T02:49:08.210 回答
1

提供的唯一线程安全保证是对象将被“安全发布”。也就是说,它们将立即对所有线程可见(这包括对对象的引用及其内部状态)。

示例:如果线程 A 写入 X,而线程 B 读取,则 B 保证在 A 离开时看到 X。换句话说,读写操作与它们发生的顺序是一致的。

还有其他方法可以完成相同的事情,例如使用final, or volatile, or AtomicReference, 或锁(这是线程安全集合所做的),或静态初始化程序。有关详细信息,请参阅《Java 并发实践》一书。

于 2013-09-02T15:54:45.913 回答