10. 附注 1:
我所定义的场景,是基于对以下资料了解的,比较低层,没有细看。
原文:http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
其中分析一个对象创建过程的部分摘抄如下:
singletons[i].reference = new Singleton();
to the following (note that the Symantec JIT using a handle-based object
allocation system).
0206106A mov eax,0F97E78h
0206106F call 01F6B210 ; allocate space for
; Singleton, return
result in eax
02061074 mov dword ptr [ebp],eax ; EBP is
&singletons[i].reference
; store the
unconstructed object here.
02061077 mov ecx,dword ptr [eax] ; dereference the
handle to
; get the raw pointer
02061079 mov dword ptr [ecx],100h ; Next 4 lines are
0206107F mov dword ptr [ecx+4],200h ; Singleton's inlined
constructor
11. 02061086 mov dword ptr [ecx+8],400h
0206108D mov dword ptr [ecx+0Ch],0F84030h
As you can see, the assignment to singletons[i].reference is performed before
the constructor for Singleton is called. This is completely legal under the
existing Java memory model, and also legal in C and C++ (since neither of
them have a memory model).
另外,从 JVM 创建一个对象的过程来看,分为:“装载” “连接” “初始化”三个步骤。
, ,
在连接步骤中包含“验证” “准备” “解析”这几个环节。
, ,
为一个对象分配内存的过程是在连接步骤的准备环节,它是先于“初始化”步骤的,而构造函
数的执行是在“初始化”步骤中的。
附注 2,
Java6 API 文档中对于内存一致性(Memory Consistency Properties)的描述:
内存一致性属性
Java Language Specification 第 17 章定义了内存操作(如共享变量的读写)的
happen-before 关系。只有写入操作 happen-before 读取操作时,才保证一个线程写入的
结果对另一个线程的读取是可视的。synchronized 和 volatile 构造 happen-before 关系,
Thread.start() 和 Thread.join() 方法形成 happen-before 关系。尤其是:
线程中的每个操作 happen-before 稍后按程序顺序传入的该线程中的每个操作。