JAvaにおけるDouble-Checked Locking二重ロックのテストコード
5403 ワード
JAvaにおけるDouble-Checked Locking二重ロックのテストコード
1
package
test;
2
3
public
class
testClone {
4
volatile
boolean
isInit;
5
6
volatile
Foo foo;
7
8
volatile
int
time
=
1
;
9
10
public
class
Foo {
11
volatile
int
flg;
12
13
public
Foo() {
14
flg
=
0
;
15
try
{
16
Thread.sleep(time);
17
}
catch
(InterruptedException e) {
18
}
19
++
flg;
20
System.out.println(
"
Foo inited
"
);
21
}
22
}
23
24
public
static
void
main(String[] args)
throws
InterruptedException {
25
testClone t
=
new
testClone();
26
t.test();
27
}
28
29
public
void
test() {
30
for
(
int
i
=
0
; i
<
5
;
++
i) {
31
WorkThread t
=
new
WorkThread();
32
t.start();
33
}
34
35
for
(;;) {
36
try
{
37
Thread.sleep(
1000
);
38
}
catch
(InterruptedException e) {
39
}
40
time
=
1000
;
41
synchronized
(
this
) {
42
foo
=
null
;
43
}
44
}
45
}
46
47
public
Foo bar() {
48
Foo f
=
foo;
49
if
(f
==
null
) {
50
synchronized
(
this
) {
51
if
(foo
==
null
) {
52
foo
=
new
Foo();
53
}
54
return
foo;
55
}
56
}
57
return
f;
58
}
59
60
public
class
WorkThread
extends
Thread {
61
public
void
run() {
62
for
(;;) {
63
try
{
64
65
Foo f
=
bar();
66
if
(f.flg
==
0
) {
67
System.out.println(f.flg);
68
}
69
}
catch
(Throwable e) {
70
e.printStackTrace();
71
}
72
}
73
}
74
}
75
}
76
1.4.2 jdkコンパイル実行.長時間実行すると、jit最適化によるFooの割り当てが完了すると、Fooコンストラクタが初期化されずにそのアドレスをfooに付与するというネット上のエラーは発見されませんでした.jitはコードを最適化したと信じています.Double-Checked Lockingに関する海外サイトの記事http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
A test case showing that it doesn't work
Paul Jakubik found an example of a use of double-checked locking that did not work correctly. A slightly cleaned up version of that code is available here.
When run on a system using the Symantec JIT, it doesn't work. In particular, the Symantec JIT compiles
to the following (note that the Symantec JIT using a handle-based object allocation system).
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).上は海外サイトから与えられたjitコードと説明です.
1
package
test;
2
3
public
class
testClone {
4
volatile
boolean
isInit;
5
6
volatile
Foo foo;
7
8
volatile
int
time
=
1
;
9
10
public
class
Foo {
11
volatile
int
flg;
12
13
public
Foo() {
14
flg
=
0
;
15
try
{
16
Thread.sleep(time);
17
}
catch
(InterruptedException e) {
18
}
19
++
flg;
20
System.out.println(
"
Foo inited
"
);
21
}
22
}
23
24
public
static
void
main(String[] args)
throws
InterruptedException {
25
testClone t
=
new
testClone();
26
t.test();
27
}
28
29
public
void
test() {
30
for
(
int
i
=
0
; i
<
5
;
++
i) {
31
WorkThread t
=
new
WorkThread();
32
t.start();
33
}
34
35
for
(;;) {
36
try
{
37
Thread.sleep(
1000
);
38
}
catch
(InterruptedException e) {
39
}
40
time
=
1000
;
41
synchronized
(
this
) {
42
foo
=
null
;
43
}
44
}
45
}
46
47
public
Foo bar() {
48
Foo f
=
foo;
49
if
(f
==
null
) {
50
synchronized
(
this
) {
51
if
(foo
==
null
) {
52
foo
=
new
Foo();
53
}
54
return
foo;
55
}
56
}
57
return
f;
58
}
59
60
public
class
WorkThread
extends
Thread {
61
public
void
run() {
62
for
(;;) {
63
try
{
64
65
Foo f
=
bar();
66
if
(f.flg
==
0
) {
67
System.out.println(f.flg);
68
}
69
}
catch
(Throwable e) {
70
e.printStackTrace();
71
}
72
}
73
}
74
}
75
}
76
1.4.2 jdkコンパイル実行.長時間実行すると、jit最適化によるFooの割り当てが完了すると、Fooコンストラクタが初期化されずにそのアドレスをfooに付与するというネット上のエラーは発見されませんでした.jitはコードを最適化したと信じています.Double-Checked Lockingに関する海外サイトの記事http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
A test case showing that it doesn't work
Paul Jakubik found an example of a use of double-checked locking that did not work correctly. A slightly cleaned up version of that code is available here.
When run on a system using the Symantec JIT, it doesn't work. In particular, the Symantec JIT compiles
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
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).上は海外サイトから与えられたjitコードと説明です.