下面的例子来自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");
}
}
它说,Holder可能会出现在另一个处于不一致状态的线程中,而另一个线程可能会观察到一个部分构造的对象。这怎么会发生呢?你能用上面的例子给出一个场景吗?
此外,它还指出,在某些情况下,线程可能会在第一次读取字段时看到过时的值,然后在下一次看到更新的值,这就是为什么assertSanity
会抛出AssertionError
。如何抛出AssertionError
?
根据进一步的阅读,解决这个问题的一种方法是通过使变量n
final来使Holder
不可变。现在,让我们假设Holder
不是不可变的,但实际上是不可变的。
为了安全地发布这个对象,我们是否必须将holder初始化设为静态,并将其声明为易失性(静态初始化和易失性或只声明易失性)?
如下所示:
public class SomeClass {
public static volatile Holder holder = new Holder(42);
}
https://stackoverflow.com/questions/16107683
复制相似问题