我想知道JAVA中synchronized和final之间的关系。我已经阅读了一些文章,每个人都提到应该使用final字段初始化构造函数中的对象,否则未初始化的对象可能会导致使用同一对象的多个线程之间的同步问题。
有关。例如以下代码:
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;
}
}
}
读者可以正确读取x的值,但可能会将y的值读为0,因为它未被声明为final。
为什么会这样?
答案 0 :(得分:2)
这与最终字段语义有关。 JLS #17.5给出了一个很好的总结:
最终字段的使用模型很简单:在该对象的构造函数中设置对象的最终字段;并且在对象的构造函数完成之前,不要在另一个线程可以看到的地方写入对正在构造的对象的引用。如果遵循此规则,那么当另一个线程看到该对象时,该线程将始终看到该对象的最终字段的正确构造版本。
换句话说,如果您在构造期间不让this
转义,则可以保证所有线程都能看到x的正确值(即3)。
关于其他字段(y),在没有同步的情况下,不保证将看到哪个值(默认值或构造函数值)。
答案 1 :(得分:-1)
final
字段与线程无关。我怀疑你正在考虑的volatile
字段的行为有点像你描述的那样。