关于并发性,最终关键字究竟保证了什么?
我想我已经读到,字段上的最后一个关键字保证,如果线程1实例化包含该字段的对象,那么如果线程2具有对该对象的引用(前提是它已正确构造),则线程2将始终看到该字段的初始化值。它还在JLS中说
[线程 2] 还将看到由最终字段引用的任何对象或数组的版本,这些字段至少与最终字段一样最新。(JLS第17.5节)
这意味着如果我有A类
class A {
private final B b = new B();
private int aNotFinal = 2;
...
和 B 类
class B {
private final int bFinal = 1;
private int bNotFinal = 2;
...
则 aNotFinal 不能保证在线程 2 获取对类 A 的引用时进行初始化,但字段 bNotFinal 是,因为 B 是由 JLS 中指定的最终字段引用的对象。
我有这个权利吗?
编辑:
发生这种情况的一种情况是,如果我们有两个线程同时在类C的同一实例上执行getA()
class C {
private A a;
public A getA(){
if (a == null){
// Thread 1 comes in here because a is null. Thread B doesn't come in
// here because by the time it gets here, object c
// has a reference to a.
a = new A();
}
return a; // Thread 2 returns an instance of a that is not fully
// initialized because (if I understand this right) JLS
// does not guarantee that non-final fields are fully
// initialized before references get assigned
}
}