下面的例子来自Brian Goetz的书"Java Concurrency in Practice",第3章,第3.5.1节.这是不正确发布对象的示例
class someClass {
public Holder holder;
public void initialize() {
holder = new Holder(42);
}
}
public class Holder {
private int n;
public Holder(int n) { this.n = n; }
public void assertSanity() {
if (n!=n)
throw new AssertionError("This statement is false");
}
}
Run Code Online (Sandbox Code Playgroud)
它表示Holder可能出现在另一个处于不一致状态的线程中,而另一个线程可能会观察到部分构造的对象.怎么会发生这种情况?你能用上面的例子给出一个场景吗?
此外,它继续说有一种情况,当一个线程第一次读取一个字段时可能会看到一个陈旧的值,然后下次再看到一个更新的值,这就是assertSanity可以抛出断言错误的原因.如何抛出assertionError?
从进一步阅读,解决这个问题的一种方法是通过使变量'n'最终使Holder不可变.现在,让我们假设持有人不是无法忍受的,而是有效的不可改变的.为了安全地发布这个对象,我们是否必须使holder初始化为静态并将其声明为volatile(静态初始化和volatile或者只是volatile)?就像是
public class someClass {
public static volatile Holder holder = new Holder(42);
}
Run Code Online (Sandbox Code Playgroud)
感谢您的帮助.
存储在线程安全集合(如CopyOnWriteArrayList)中的对象是否安全?让我们说存储的对象是可变的(不是线程安全的)然后集合(这里是CopyOnWriteArrayList)是线程安全的事实提供了对存储在其中的引用的线程安全性的任何保证吗?