我们知道Synchronized存在锁升级的情况
- 无锁状态
- 匿名偏向锁状态
- 偏向锁状态
- 轻量级锁状态
- 重量级锁状态
通过查看锁对象的markword的后三位来确定,来确定锁状态
| 锁类型 | 偏向锁 | 锁标志 | 总体标志 |
|---|---|---|---|
| 无锁 | 0 | 01 | 001 |
| 偏向锁 | 1 | 01 | 101 |
| 轻量级锁 | 0 | 00 | 000 |
| 重量级锁 | 0 | 10 | 010 |
这里我们还是通过openjdk的jol来查看markword,maven引入
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.9</version>
</dependency>
无锁
public void printNoLock(){
System.out.println("打印无锁状态");
System.out.println(ClassLayout.parseInstance(new Object()).toPrintable());
System.out.println("==============================================================");
}
打印日志使用**标记出来就是锁标识位,当前001为无锁状态
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000**001** 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 00 1c 5d 75 (00000000 00011100 01011101 01110101) (1969036288)
12 4 (object header) e5 01 00 00 (11100101 00000001 00000000 00000000) (485)
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
匿名偏向锁
偏向锁启动有4秒时延
public void printAnonymousBiasLock(){
System.out.println("=====================打印匿名偏向锁状态=====================");
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
Object object = new Object();
System.out.println(ClassLayout.parseInstance(object).toPrintable());
System.out.println("==============================================================");
}
打印日志使用**标记出来就是锁标识位,当前101为偏向锁状态,并且后面都是0000没有记录偏向锁的归属
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 05 00 00 00 (00000**101** 00000000 00000000 00000000) (5)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
偏向锁
public void printBiasLock(){
System.out.println("=====================打印偏向锁状态=====================");
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
Object object = new Object();
synchronized (object){
System.out.println(ClassLayout.parseInstance(object).toPrintable());
}
System.out.println("==============================================================");
}
打印日志使用**标记出来就是锁标识位,当前101为偏向锁状态,并且后面不是0000,记录偏向锁的归属
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 05 49 0e 76 (00000**101** 01001001 00001110 01110110) (1980647685)
4 4 (object header) e9 01 00 00 (11101001 00000001 00000000 00000000) (489)
8 4 (object header) e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
轻量级锁
public void printLightWeightLock(){
System.out.println("=====================打印无锁升级成轻量级锁状态=====================");
Object object = new Object();
System.out.println(ClassLayout.parseInstance(object).toPrintable());
synchronized (object){
System.out.println(ClassLayout.parseInstance(object).toPrintable());
}
System.out.println("==============================================================");
}
进入轻量级锁的方式有很多,比如如果偏向锁未启动,直接资源竞争就会直接进入轻量级锁状态
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 48 f6 2f 27 (01001**000** 11110110 00101111 00100111) (657454664)
4 4 (object header) 03 00 00 00 (00000011 00000000 00000000 00000000) (3)
8 4 (object header) e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
重量级锁
public void printHeavyWeightLock(){
System.out.println("打印重量级锁状态");
Object object = new Object();
for(int i=0;i<10;i++){
new Thread(()->{
synchronized (object){
System.out.println(ClassLayout.parseInstance(object).toPrintable());
}
}).start();
}
System.out.println("==============================================================");
}
锁竞争激烈就会申请为重量级锁
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) fa b8 48 41 (11111**010** 10111000 01001000 01000001) (1095284986)
4 4 (object header) a9 02 00 00 (10101001 00000010 00000000 00000000) (681)
8 4 (object header) e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total