【发布时间】:2018-05-24 09:09:53
【问题描述】:
我阅读了几个相关问题,但没有一个解释安全发布持有人的方法。我仍然对 Java Concurrency in Practice 中的示例感到困惑,第 3.5 节:
有类Holder:
public Holder {
private int n;
public Holder(int n) { this.n = n };
public void assertSanity() {
if(n != n)
throw new AssertionError("This statement is false.");
}
}
及其不安全的发布:
//unsafe publication
public Holder holder;
public void initialize() {
holder = new Holder(42);
}
AssertionError 可能会被抛出,我同意。作者写道,这是因为出版不安全,但另一方面没有答案: 正确的发布方式是什么? 他们指出了 4 个安全的发布习语,但我不明白,为什么它们会在上述情况下起作用:
为了安全地发布对象,对对象的引用和 对象的状态必须同时对其他线程可见。 正确构造的对象可以通过以下方式安全发布:
- 从静态初始化器初始化对象引用;
- 将对其的引用存储到易失性字段或 AtomicReference 中;
- 将对它的引用存储到正确构造的对象的最终字段中;
- 或将对其的引用存储到由以下人员正确保护的字段中 一把锁。
我同意 1&4,但怀疑为什么以下出版物会起作用:
//safe publication
public volatile Holder holder;
或
//safe publication
public final Holder holder;
volatile & final 只对引用有影响,对被引用的对象状态没有影响,所以我认为 AssertionError 仍然可能,对吧?
作者展示了如何使持有者免受不安全出版物的影响,而不是对出版物进行改进,方法是:
private final int n;
我很好奇以下是否也可以使用?它与(有效)不变性有何联系?
private volatile int n;
这是我的第一个问题,谢谢你的帮助!
【问题讨论】:
标签: java multithreading immutability