流程图
对象锁标志
| 锁状态 | 偏向锁 | 锁的标志位 |
|---|---|---|
| 无锁 | 0 | 01 |
| 偏向锁 | 1 | 01 |
| 轻量级锁 | 00 | |
| 重量级锁 | 10 |
- 无状态-->偏向锁
- 无状态-->轻量级锁
- 偏向锁-->轻量级锁
- 轻量级锁-->重量级锁
代码测试
用到的jar包
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.10</version>
</dependency>
import org.openjdk.jol.info.ClassLayout;
public class sync3 {
public static void main(String[] args) throws InterruptedException {
// jvm默认延时4s创建的对象都自动开启偏向锁
// 1. 无状态-->偏向锁
final User user1 = new User();
Thread.sleep(5000);
final User user2 = new User();
System.out.println("jvm一开始就创建的对象,是无状态001: " + ClassLayout.parseInstance(user1).toPrintable());
System.out.println("jvm开始4s后创建的对象,是偏向锁101: " + ClassLayout.parseInstance(user2).toPrintable());
System.out.println("******************************************\n");
2. 无状态-->轻量级锁
synchronized (user1){
System.out.println("无状态->轻量级锁00(带线程id): " + ClassLayout.parseInstance(user1).toPrintable());
}
System.out.println("无状态01(带线程id): " + ClassLayout.parseInstance(user1).toPrintable());
synchronized (user2){
System.out.println("偏向锁101(带线程id): " + ClassLayout.parseInstance(user2).toPrintable());
}
System.out.println("偏向锁101(带线程id): " + ClassLayout.parseInstance(user2).toPrintable());
System.out.println("******************************************\n");
synchronized (user2) {
System.out.println("偏向锁101(带线程id): " + ClassLayout.parseInstance(user2).toPrintable());
}
System.out.println("******************************************\n");
// 线程加锁,锁升级
// 3. 偏向锁-->轻量级锁
new Thread(() -> {
synchronized (user2){
System.out.println("轻量级锁00: " + ClassLayout.parseInstance(user2).toPrintable());
try{
Thread.sleep(3000);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println("轻量级->重量级10: " + ClassLayout.parseInstance(user2).toPrintable());
}
}).start();
Thread.sleep(1000);
// 在上一个线程还未完成,加入另外一个线程加入锁的抢占,导致锁再次升级
// 4. 轻量级锁-->重量级锁
new Thread(() -> {
synchronized (user2){
System.out.println("重量级10: " + ClassLayout.parseInstance(user2).toPrintable());
}
}).start();
}
}
红色标记是锁的标志位
结果:
jvm一开始就创建的对象,是无状态001: com.company.Thread.Concurrent.User object internals:
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) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
12 4 java.lang.String User.id null
16 4 java.lang.String User.name null
20 4 (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
jvm开始4s后创建的对象,是偏向锁101: com.company.Thread.Concurrent.User object internals:
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) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
12 4 java.lang.String User.id null
16 4 java.lang.String User.name null
20 4 (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
******************************************
无状态->轻量级锁00(带线程id): com.company.Thread.Concurrent.User object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 50 f7 cd 02 (01010000 11110111 11001101 00000010) (47052624)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
12 4 java.lang.String User.id null
16 4 java.lang.String User.name null
20 4 (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
无状态01(带线程id): com.company.Thread.Concurrent.User object internals:
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) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
12 4 java.lang.String User.id null
16 4 java.lang.String User.name null
20 4 (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
偏向锁101(带线程id): com.company.Thread.Concurrent.User object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 05 28 de 02 (00000101 00101000 11011110 00000010) (48113669)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
12 4 java.lang.String User.id null
16 4 java.lang.String User.name null
20 4 (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
偏向锁101(带线程id): com.company.Thread.Concurrent.User object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 05 28 de 02 (00000101 00101000 11011110 00000010) (48113669)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
12 4 java.lang.String User.id null
16 4 java.lang.String User.name null
20 4 (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
******************************************
偏向锁101(带线程id): com.company.Thread.Concurrent.User object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 05 28 de 02 (00000101 00101000 11011110 00000010) (48113669)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
12 4 java.lang.String User.id null
16 4 java.lang.String User.name null
20 4 (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
******************************************
轻量级锁00: com.company.Thread.Concurrent.User object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 98 f1 3f 1b (10011000 11110001 00111111 00011011) (457175448)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
12 4 java.lang.String User.id null
16 4 java.lang.String User.name null
20 4 (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
sleep 3s
轻量级->重量级10: com.company.Thread.Concurrent.User object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 3a 98 ed 02 (00111010 10011000 11101101 00000010) (49125434)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
12 4 java.lang.String User.id null
16 4 java.lang.String User.name null
20 4 (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
重量级10: com.company.Thread.Concurrent.User object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 3a 98 ed 02 (00111010 10011000 11101101 00000010) (49125434)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
12 4 java.lang.String User.id null
16 4 java.lang.String User.name null
20 4 (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
以上就是锁升级的基本过程。