本文使用汇编对 volatile 关键字进行分析
-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:+TraceClassLoading -Xcomp -XX:CompileCommand=dontinline,*VolatileTest.main -XX:CompileCommand=compileonly,*VolatileTest.main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.pohvii.note.basic.concurrent;
/**
* @author zhanglei
* @date 2021/5/31
*/
public class NoVolatileTest {
static int a = 0;
public static void main(String[] args) {
if (a == 0) {
a++;
}
}
}
0x000000010af3a220: sub $0x18,%rsp 0x000000010af3a227: mov %rbp,0x10(%rsp) ;*synchronization entry ; - com.pohvii.note.basic.concurrent.NoVolatileTest::main@-1 (line 11) 0x000000010af3a22c: movabs $0x66ab68b18,%r10 ; {oop(a 'java/lang/Class' = 'com/pohvii/note/basic/concurrent/NoVolatileTest')} 0x000000010af3a236: mov 0x68(%r10),%r8d ;*getstatic a ; - com.pohvii.note.basic.concurrent.NoVolatileTest::main@0 (line 11) 0x000000010af3a23a: test %r8d,%r8d 0x000000010af3a23d: je 0x000000010af3a24b ;*return ; - com.pohvii.note.basic.concurrent.NoVolatileTest::main@14 (line 14) 0x000000010af3a23f: add $0x10,%rsp 0x000000010af3a243: pop %rbp 0x000000010af3a244: test %eax,-0x5c9a24a(%rip) # 0x00000001052a0000 ; {poll_return} 0x000000010af3a24a: retq 0x000000010af3a24b: inc %r8d 0x000000010af3a24e: mov %r8d,0x68(%r10) ;*putstatic a ; - com.pohvii.note.basic.concurrent.NoVolatileTest::main@11 (line 12)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.pohvii.note.basic.concurrent;
/**
* @author zhanglei
* @date 2021/5/31
*/
public class VolatileTest {
static volatile int a = 0;
public static void main(String[] args) {
if (a == 0) {
a++;
}
}
}
0x0000000109ca1360: sub $0x18,%rsp 0x0000000109ca1367: mov %rbp,0x10(%rsp) ;*synchronization entry ; - com.pohvii.note.basic.concurrent.VolatileTest::main@-1 (line 11) 0x0000000109ca136c: movabs $0x66ab68ac0,%r10 ; {oop(a 'java/lang/Class' = 'com/pohvii/note/basic/concurrent/VolatileTest')} 0x0000000109ca1376: mov 0x68(%r10),%r8d ;*getstatic a ; - com.pohvii.note.basic.concurrent.VolatileTest::main@0 (line 11) 0x0000000109ca137a: test %r8d,%r8d 0x0000000109ca137d: je 0x0000000109ca138b ;*return ; - com.pohvii.note.basic.concurrent.VolatileTest::main@14 (line 14) 0x0000000109ca137f: add $0x10,%rsp 0x0000000109ca1383: pop %rbp 0x0000000109ca1384: test %eax,-0x5d1038a(%rip) # 0x0000000103f91000 ; {poll_return} 0x0000000109ca138a: retq 0x0000000109ca138b: mov 0x68(%r10),%r8d 0x0000000109ca138f: inc %r8d 0x0000000109ca1392: mov %r8d,0x68(%r10) 0x0000000109ca1396: lock addl $0x0,(%rsp) ;*putstatic a ; - com.pohvii.note.basic.concurrent.VolatileTest::main@11 (line 12)
源代码部分:两者仅第8行不同,一个使用了 volatile 变量,另一个未使用
汇编码部分:使用 volatile 变量的汇编码在 a++ 之前多了一次读的操作,之后多了一条 lock 前缀的命令
- stack
stack starts at a high memory address and grows downwards
- $
Immediate values are constants, and are prefixed by a $
- %
Register names are prefixed by a %
- rsp
stack pointer, points to the top of the current stack frame
- rbp
base pointer, points to the base of the current stack frame
- LOCK (prefix)
The LOCK prefix ensures that the CPU has exclusive ownership of the appropriate cache line for the duration of the operation, and provides certain additional ordering guarantees. This may be achieved by asserting a bus lock, but the CPU will avoid this where possible. If the bus is locked then it is only for the duration of the locked instruction.
The cache coherency mechanism automatically prevents two or more processors that have cached the same area of memory from simultaneously modifying data in that area.
没有评论 :
发表评论