测试代码
为了更清楚的看 synchronized 的锁的升级的过程,我们用代码来打印对象的布局,使用的类库是:
1 2 3 4 5 6
| <dependency> <groupId>org.openjdk.jol</groupId> <artifactId>jol-core</artifactId> <version>0.14</version> <scope>provided</scope> </dependency>
|
具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| static A obj;
public static void main(String[] args) throws InterruptedException { obj = new A();
System.out.println(ClassLayout.parseInstance(obj).toPrintable()); printHeader();
printHeader(); Thread thread = new Thread(() -> { printHeader(); }); Thread thread2 = new Thread(() -> { printHeader(); }); thread.start(); thread2.start(); thread.join(); thread2.join(); } private static void printHeader() { synchronized (obj) { System.out.println(ClassLayout.parseInstance(obj).toPrintable()); System.out.println("========"); } }
|
日志打印结果如下:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 47 c1 00 f8 (01000111 11000001 00000000 11111000) (-134168249)
12 4 (loss due to the next object alignment)
由于 java 的对象是小端存储,所以真实的展示和实际书写是相反的方向,实际的例子中,展示的 001 代表锁的内容。
默认状态
1. 未加锁 ,锁状态是 001(无锁不可偏向)
1 2 3 4 5
| OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 47 c1 00 f8 (01000111 11000001 00000000 11111000) (-134168249) 12 4 (loss due to the next object alignment)
|
2. 主线程进入,锁升级为 00(轻量级锁)
1 2 3 4 5
| OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) c0 f5 81 02 (11000000 11110101 10000001 00000010) (42071488) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 47 c1 00 f8 (01000111 11000001 00000000 11111000) (-134168249) 12 4 (loss due to the next object alignment)
|
3. 线程 1 进入,无其他线程竞争 00
1 2 3 4 5
| OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) c0 f5 81 02 (11000000 11110101 10000001 00000010) (42071488) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 47 c1 00 f8 (01000111 11000001 00000000 11111000) (-134168249) 12 4 (loss due to the next object alignment)
|
4. 线程 2 等线程 1 执行玩后进入,无其他线程竞争 00
1 2 3 4 5
| OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 38 f6 6c 1f (00111000 11110110 01101100 00011111) (527234616) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 47 c1 00 f8 (01000111 11000001 00000000 11111000) (-134168249) 12 4 (loss due to the next object alignment)
|
5. 线程 1 和线程 2 同时进入 ,存在竞争 ,升级位重量级锁 10
1 2 3 4 5
| OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 1a e7 ec 02 (00011010 11100111 11101100 00000010) (49080090) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 47 c1 00 f8 (01000111 11000001 00000000 11111000) (-134168249) 12 4 (loss due to the next object alignment)
|
◆ 打开偏向锁开关
1
| -XX:BiasedLockingStartupDelay=0
|
1. 未加锁 锁状态 101,无锁可偏向,实际是偏向锁但是没有存储线程 ID,所以还是无锁状态
1 2 3 4 5
| OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 05 00 00 00 (00000101 00000000 00000000 00000000) (5) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 47 c1 00 f8 (01000111 11000001 00000000 11111000) (-134168249) 12 4 (loss due to the next object alignment)
|
2. 主线程进入,锁状态 101,存储了线程 ID,转成真实的偏向锁。
1 2 3 4 5
| OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 05 40 41 03 (00000101 01000000 01000001 00000011) (54607877) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 47 c1 00 f8 (01000111 11000001 00000000 11111000) (-134168249) 12 4 (loss due to the next object alignment)
|
3. 线程 1 进入,无其他线程竞争,锁状态 00 (轻量锁)
1 2 3 4 5
| OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) d8 f3 7e 1e (11011000 11110011 01111110 00011110) (511636440) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 47 c1 00 f8 (01000111 11000001 00000000 11111000) (-134168249) 12 4 (loss due to the next object alignment)
|
4. 线程 2 进入,无其他线程竞争,锁状态 00 (轻量锁)
1 2 3 4 5
| OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) a8 ef 7e 1e (10101000 11101111 01111110 00011110) (511635368) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 47 c1 00 f8 (01000111 11000001 00000000 11111000) (-134168249) 12 4 (loss due to the next object alignment)
|
5. 线程 1 和线程 2 同时进入 ,存在竞争 10
1 2 3 4 5
| OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 5a e5 d1 02 (01011010 11100101 11010001 00000010) (47310170) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 47 c1 00 f8 (01000111 11000001 00000000 11111000) (-134168249) 12 4 (loss due to the next object alignment)
|
◆ 打开偏向锁开关—-同时运行对象的HashCode
1. 未加锁 锁状态 101,无锁可偏向,实际是偏向锁但是没有存储线程 ID,所以还是无锁状态
1 2 3 4 5
| OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 05 00 00 00 (00000101 00000000 00000000 00000000) (5) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 47 c1 00 f8 (01000111 11000001 00000000 11111000) (-134168249) 12 4 (loss due to the next object alignment)
|
2. 运行 hashcode 后,锁状态升级位无锁不可偏向 ,原本存放线程 ID 的位置被 hashcode 覆盖
1 2 3 4 5
| OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 05 40 62 02 (00000101 01000000 01100010 00000010) (39993349) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 47 c1 00 f8 (01000111 11000001 00000000 11111000) (-134168249) 12 4 (loss due to the next object alignment)
|
3. 线程 1 进入,无锁竞争,锁升级为轻量锁 000
1 2 3 4 5
| OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 90 f1 93 00 (10010000 11110001 10010011 00000000) (9695632) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 47 c1 00 f8 (01000111 11000001 00000000 11111000) (-134168249) 12 4 (loss due to the next object alignment)
|
4. 线程 2 进入,存在锁竞争,锁升级为轻量锁 010
1 2 3 4 5
| OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 0a e5 71 02 (00001010 11100101 01110001 00000010) (41018634) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 47 c1 00 f8 (01000111 11000001 00000000 11111000) (-134168249) 12 4 (loss due to the next object alignment)
|
◆ 锁升级基本流程