模拟synchronized锁升级过程(详细代码)

本文详细解析了Java中synchronized锁的四种状态及其转换过程,通过实例代码演示了从偏向锁到重量锁的升级机制,并展示了不同锁状态下对象头Mark Word的变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

synchronized在1.6之后发生了很大改动,做了很多优化。因为Doug Lea大师的ReentrantLock类设计的很完美,jdk开发人员表示不服,所以对synchronized做了很大的改动。

此博客针对已对synchronized锁有所了解的。

首先我们需要知道synchronized具有4种锁的状态(细分5种):

  1. 无锁无偏向
  2. 无锁可偏向
  3. 有锁已偏向
  4. 轻量锁
  5. 重量锁

在JVM中,偏向锁的启动时会有延迟触发的,因为jvm在启动线程之前会有许多synchronized操作,jvm内部默认这些操作为轻量级操作并非偏向操作。因为对于偏向锁的升级,是十分消耗性能的,需要先撤销再升级。

请看下列代码:


public class Main {
    static class A{
        int a = 0;
        boolean f = false;
    }

    public static void main(String[] args) throws InterruptedException {
        Thread.sleep(5000);//这里为什么要延迟5s,上文解释了。
        A a = new A();
        System.out.println(ClassLayout.parseInstance(a).toPrintable(a));
        Thread t1 = new Thread(() -> {
            synchronized (a) {
                System.out.println(Thread.currentThread().getName() + " 进入偏向锁状态");
                System.out.println(ClassLayout.parseInstance(a).toPrintable(a));
            }
        });
        t1.start();
        t1.join();//保证t1线程执行结束后执行main线程,模拟交替运行,此时会发生锁升级

        Thread t2 = new Thread(() -> {
            try {
                Thread.sleep(100);//保证main线程先获取a锁,然后竞争a锁
                synchronized (a){
                    System.out.println(Thread.currentThread().getName() + " 进入重量锁状态");
                    System.out.println(ClassLayout.parseInstance(a).toPrintable(a));
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t2.start();

        synchronized (a){
            System.out.println(Thread.currentThread().getName() + " 进入轻量锁状态");
            System.out.println(ClassLayout.parseInstance(a).toPrintable(a));
            Thread.sleep(2000);
        }
    }
}

运行结果如下:

我们观察红色下划线的数字,这3个为Mark Word中关于锁的3个二进制位,第一个为偏向符号,后两位为锁状态。

1.首先代码中我们延迟5s,保证进入可偏向的状态(101),否则刚开始打印出来结果为(001)。

2.后续启动一个线程t1,拿去a锁, 变成有锁已偏向状态(101)。

3.线程t1启动完成后,让主线程拿去a锁,变成轻量锁状态(000).

4.此时主线程在休眠2000ms,锁未释放,线程t2去争夺锁a,发生不同互斥,此时锁升级为重量级锁(010)。


Main$A 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 f8 (01000011 11000001 00000000 11111000) (-134168253)
     12     4       int A.a                                       0
     16     1   boolean A.f                                       false
     17     7           (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 7 bytes external = 7 bytes total

Thread-0 进入偏向锁状态
Main$A object internals:
 OFFSET  SIZE      TYPE DESCRIPTION                               VALUE
      0     4           (object header)                           05 28 1c 21 (00000101 00101000 00011100 00100001) (555493381)
      4     4           (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4           (object header)                           43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)
     12     4       int A.a                                       0
     16     1   boolean A.f                                       false
     17     7           (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 7 bytes external = 7 bytes total

main 进入轻量锁状态
Main$A object internals:
 OFFSET  SIZE      TYPE DESCRIPTION                               VALUE
      0     4           (object header)                           68 f8 74 02 (01101000 11111000 01110100 00000010) (41220200)
      4     4           (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4           (object header)                           43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)
     12     4       int A.a                                       0
     16     1   boolean A.f                                       false
     17     7           (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 7 bytes external = 7 bytes total

Thread-1 进入重量锁状态
Main$A object internals:
 OFFSET  SIZE      TYPE DESCRIPTION                               VALUE
      0     4           (object header)                           3a 28 62 1c (00111010 00101000 01100010 00011100) (476194874)
      4     4           (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4           (object header)                           43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)
     12     4       int A.a                                       0
     16     1   boolean A.f                                       false
     17     7           (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 7 bytes external = 7 bytes total


Process finished with exit code 0
 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值