对象内部结构
偏向锁:会把加锁线程的id(threadId 【54bit】)写入到对象头的mark word里面
对象结构说明
对象需先启用为偏向锁才能升级变为偏向锁,偏向锁不会主动释放
偏向锁->轻量级锁:有线程加锁,之后只要有其他线程来争锁,偏向锁立刻会升级为轻量级锁
轻量级锁->重量级锁:多个线程来竞争,当线程不断地CAS自旋都拿不到锁,达到一定自旋次数,才转化为重量级锁。
升级为重量级锁后,指针指向monitor
锁升级实践
引入依赖
<!-- 帮助打印对象内部的组成结构-->
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.10</version>
</dependency>
public class LockUpgrade {
public static void main(String[] args) throws InterruptedException {
User user = new User();
System.out.println("无状态(001): "+ ClassLayout.parseInstance(user).toPrintable());
/*java默认延时4s后自动开启偏向锁,可通过 -XX:BiasedLockingStarttupDelay=0 取消延时;
如果不要偏向锁,可通过 -XX:-UseBisasedLocking = false 来设置
**/
Thread.sleep(5000); //为了开启偏向锁
User user1 = new User();
System.out.println("启用偏向锁(101): "+ ClassLayout.parseInstance(user1).toPrintable());
for (int i = 0; i <2 ; i++) {
synchronized (user1){
System.out.println("偏向锁(101)(带线程id): "+ ClassLayout.parseInstance(user1).toPrintable());
}
System.out.println("偏向锁释放(101)(带线程id): "+ ClassLayout.parseInstance(user1).toPrintable());
}
new Thread( ()-> {
synchronized (user1) {
System.out.println("轻量级锁(00) : " + ClassLayout.parseInstance(user1).toPrintable());
System.out.println("睡眠3秒钟===============");
try {
Thread.sleep(3000);//目的是让 后面启动的线程过来 竞争锁 让轻量级锁变为重量级锁
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("轻量-->重量(10) : " + ClassLayout.parseInstance(user1).toPrintable());
}
}
).start();
Thread.sleep(1000);//上面锁未释放,升级为重量级锁
new Thread(()->{
synchronized (user1){
System.out.println("重量(10) : "+ ClassLayout.parseInstance(user1).toPrintable());
}
}).start();
}
}
控制台打印情况
无状态(001): lock.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.Integer 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): lock.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.Integer 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): lock.User object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 05 30 90 02 (00000101 00110000 10010000 00000010) (43003909)
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.Integer 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): lock.User object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 05 30 90 02 (00000101 00110000 10010000 00000010) (43003909)
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.Integer 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): lock.User object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 05 30 90 02 (00000101 00110000 10010000 00000010) (43003909)
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.Integer 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): lock.User object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 05 30 90 02 (00000101 00110000 10010000 00000010) (43003909)
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.Integer 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) : lock.User object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 88 f2 f5 1a (10001000 11110010 11110101 00011010) (452326024)
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.Integer 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
睡眠3秒钟===============
轻量-->重量(10) : lock.User object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 9a f5 90 17 (10011010 11110101 10010000 00010111) (395376026)
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.Integer 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) : lock.User object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 9a f5 90 17 (10011010 11110101 10010000 00010111) (395376026)
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.Integer 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
Process finished with exit code 0
说明