我目前正在阅读Brian Goetz的Java Concurrency in Practice.在第51页.在其中一个脚注中,他说:
虽然它可能似乎在构造函数中设置字段的值写入这些字段中的第一个值,因此不存在"老"值看作为过时的值,子类的构造函数运行之前Object构造函数首先写入默认值到所有领域.因此,可以将字段的默认值视为陈旧值.
所以,最终领域的概念现在还不清楚.考虑样本类:
public class MyClass{ private final MyImmutableClass mic; public MyClass(){ mic = MyImmutableClass.empty(); } }
根据上面的脚注,mic
字段被分配两次,一次由Object
构造函数指定,一次由构造MyClass
函数本身指定.现在,假设我们MyClass
不安全地发布了一个对象(例如通过public
字段):
public final MyClass mc;
谁保证mc
一致状态下的任何线程都能始终观察到?为什么有些线程不会意外地观察到默认值?
据我所知,该final
字段本身仅保证在对象构造之后不能分配引用.如果我们宣布mc
挥发性,那将是明确的.读取该字段的任何线程都应该直接从内存中读取它.禁止从缓存中读取它.
UPD:出版示例:
public static void main(String[] args){ class MyRunnable implements Runnable(){ private SomeClass sc; public MyRunnable(SomeClass sc){ this.sc = sc; } public void run(){ //do some with sc } } SomeClass sc = getInitialized(); ExecutorService es = Executors.newFixedThreadPool(10); MyRunnable mr = new MyRunnable(sc); //submiting mr to es 10 times es.awaitTemination(); es.shutdown(); } private static SomeClass getInitialized(){ SomeClass sc = new SomeClass(); sc. initialize(); return sc; } public class SomeClass public MyClass mc; public void initialize(){ mc = new MyClass(); } }
一个SomeClass
实例将在多个线程中发布.某些线程可以观察到该mic
字段的默认值吗?
mc
在您的示例中是一个实例变量.这意味着您必须拥有一个完全初始化的类实例,mc
以便访问mc
某些实例的任何代码都不会抛出NullPointerException
.因此,mc
肯定会在访问时初始化.