【发布时间】:2013-11-13 23:34:28
【问题描述】:
当我提到 JMM 以获取与“最终”相关的保证时,我最近感到困惑。这是 JMM 的摘录和示例
图 4 给出了一个示例,展示了最终字段与正常字段的比较。班上 FinalFieldExample 有一个最终的 int 字段 x 和一个非最终的 int 字段 y。一个线程可能执行方法 writer(),而另一个线程可能执行方法 reader()。因为 writer() 写 f 在对象的构造函数完成后,reader() 将保证看到 f.x 的正确初始化值:它将读取值 3。但是,f.y 不是最终的;因此,reader() 方法不能保证看到它的值 4
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; // guaranteed to see 3
int j = f.y; // could see 0
}
}
}
我的困惑是对象“Obj”具有最终字段和非最终字段已完全初始化并被线程“T”引用,T 只会看到最终字段的正确值?构造后未发生突变的非最终字段呢?我知道如果它们在构造线程'T'之后发生突变,可能看不到新值(除非该字段是 volatile )。但是如果该字段是非最终的和非易失的并且在构造后没有发生突变,我该怎么办?
JVM 如何实现与 'final' 相关的保证?例如,对于 volatile 存在内存障碍。
【问题讨论】:
-
这段代码有一个错误 - 在
if(f!=null)检查之后,f可能再次显示为空。代码应该使用局部变量来缓存f -
stackoverflow.com/a/15342485/2031799 - 这就是最终字段的实现方式。从理论上讲,这个例子可能会失败,但在实践中不会。
标签: java multithreading