Java 最终和安全出版物
Java final & Safe Publication
当我阅读 jsr-133-faq 时,在问题 "How do final fields work under the new JMM?" 中,它说:
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}
static void reader() {
if (f != null) {
int i = f.x;
int j = f.y;
}
}
}
上面的 class 是如何使用 final 字段的示例。执行 reader 的线程保证看到 f.x 的值 3,因为它是最终的。不能保证看到 y 的值 4,因为它不是最终的。
这让我很困惑,因为writer中的代码不是安全发布的,执行reader的线程可能会看到f不为null,但是 f引用的对象的构造函数没有完成然而,即使 x 是最终的,也不能保证执行 reader 的线程看到 f.x.
的值 3
这是我比较疑惑的地方,不对的地方请指正,非常感谢
这就是重点,这就是 JMM 中 final 字段的优点所在。是的,编译器通常可以在对象完全构造之前就为其分配一个引用,这是 不安全 发布,因为可以在部分构造的状态下访问该对象。但是,对于 final 字段,JMM(和编译器)保证所有 final 字段将在 first、before 将引用分配给对象。当新线程访问它时,发布可能仍然不安全并且对象仍然只是部分构造,但至少最终字段将处于预期状态。来自 Java 并发实践中的第 16.3 章:
Initialization safety makes visibility guarantees only for the values
that are reachable through final fields as of the time the constructor
finishes. For values reachable through nonfinal fields, or values that
may change after construction, you must use synchronization to ensure
visibility.
我还建议阅读第 16.3 章以了解更多详细信息。
当我阅读 jsr-133-faq 时,在问题 "How do final fields work under the new JMM?" 中,它说:
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}
static void reader() {
if (f != null) {
int i = f.x;
int j = f.y;
}
}
}
上面的 class 是如何使用 final 字段的示例。执行 reader 的线程保证看到 f.x 的值 3,因为它是最终的。不能保证看到 y 的值 4,因为它不是最终的。
这让我很困惑,因为writer中的代码不是安全发布的,执行reader的线程可能会看到f不为null,但是 f引用的对象的构造函数没有完成然而,即使 x 是最终的,也不能保证执行 reader 的线程看到 f.x.
的值 3这是我比较疑惑的地方,不对的地方请指正,非常感谢
这就是重点,这就是 JMM 中 final 字段的优点所在。是的,编译器通常可以在对象完全构造之前就为其分配一个引用,这是 不安全 发布,因为可以在部分构造的状态下访问该对象。但是,对于 final 字段,JMM(和编译器)保证所有 final 字段将在 first、before 将引用分配给对象。当新线程访问它时,发布可能仍然不安全并且对象仍然只是部分构造,但至少最终字段将处于预期状态。来自 Java 并发实践中的第 16.3 章:
Initialization safety makes visibility guarantees only for the values that are reachable through final fields as of the time the constructor finishes. For values reachable through nonfinal fields, or values that may change after construction, you must use synchronization to ensure visibility.
我还建议阅读第 16.3 章以了解更多详细信息。