我正在浏览有关线程和锁的 JLS 文档http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5 http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5 .
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
}
}
}
我对本节中提到的关于如何将 f.y 视为零的上述示例(例如,17.5-1)感到困惑。
读取器线程要么将对象 f 读取为 null,在这种情况下它将不执行任何操作,要么将读取带有某些引用的对象 f。如果对象 f 有引用,则即使多个写入线程正在运行,构造函数也必须完成其执行,以便可以将引用分配给 f,并且如果构造函数已执行,则 f.y 应视为 4。
在什么条件下f.y =0 是可能的?
Thanks
在什么条件下f.y =0 是可能的?
Java 内存模型允许 JIT 编译器重新排序初始化非最终的 fields outside构造函数。这x
字段是最终字段,因此必须由 JVM 初始化,但是y
不是最终的。所以有可能是FinalFieldExample
已分配并设置为static FinalFieldExample f
但初始化的y
字段尚未完成。
引用17.5-1:
因为 writer 方法在对象的构造函数完成后写入 f,所以 reader 方法将保证看到 f.x 的正确初始化值:它将读取值 3。但是,f.y 不是最终的;因此,不能保证 reader 方法看到它的值 4。
Because f.y
不是最终的,不能保证在构造函数完成时它已经被设置并且static f
被安排了。所以就产生了竞争条件reader
可能会看到y
3 或 0 取决于这场比赛。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)