Java对象头Markword的结构

 其中,最低2位是10代表重量级锁,00代表轻量级锁,001代表无锁,101代表偏向锁。
synchronized锁在1.6的时候做了优化,当仅有一个线程竞争锁的时候,锁处于偏向锁的状态,当多个线程锁竞争不激烈的时候,锁会升级成轻量级锁,当竞争特别激烈以后,就升级成重量级锁了。
 问题是,锁升级成重量级锁以后,还能不能降级程轻量级锁或者偏向锁?
打印对象头信息
添加依赖:
 <dependency>
     <groupId>org.openjdk.jol</groupId>
     <artifactId>jol-core</artifactId>
     <version>0.9</version>
</dependency>
 
用下面一个api就够了:
ClassLayout.parseInstance(object).toPrintable();
 
测试代码
public class SynchronizedTest {
    private static Object lock  = new Object();
    public static void main(String[] args)throws Exception {
        lockUpgradeTest();
    }
    public static void lockUpgradeTest()throws Exception {
        System.out.println("业务低谷期。。。。。");
        // 偏向锁
        biz();
        System.out.println("业务高峰期开始。。。。。");
        CountDownLatch startLatch = new CountDownLatch(1);
        CountDownLatch stopLatch = new CountDownLatch(10);
        for(int i=0; i<10; i++){
            new Thread(()->{
                try{startLatch.await();}catch(Exception e){}
                // 大量锁竞争,升级成重量级锁
                biz();
                stopLatch.countDown();
            }).start();
        }
        startLatch.countDown();
        stopLatch.await();
        System.out.println("业务高峰期结束");
        // 过了一段时间,系统的访问量降下来了
        try{Thread.sleep(3000);}catch(Exception e){}
        // 此时的锁变成了轻量级锁
        biz();
        // 退出同步代码块变成了无锁
        System.out.println("退出同步代码块以后:");
        System.out.println(Thread.currentThread().getName() + ":" + ClassLayout.parseInstance(lock).toPrintable());
    }
    public static void biz(){
        synchronized (lock){
            System.out.println(Thread.currentThread().getName() + ":" + ClassLayout.parseInstance(lock).toPrintable());
            try{Thread.sleep(1);}catch(Exception e){}
        }
    }
 
输出结果如下:
业务低谷期。。。。。
 OFFSET  SIZE   TYPE DESCRIPTION         VALUE
      0     4        (object header)     05 f0 34 a8 (00000101 11110000 00110100 10101000) (-1472925691)
      4     4        (object header)     31 02 00 00 (00110001 00000010 00000000 00000000) (561)
      8     4        (object header)     00 10 00 00 (00000000 00010000 00000000 00000000) (4096)
     12     4        (loss due to the next object alignment)
业务高峰期开始。。。。
 OFFSET  SIZE   TYPE DESCRIPTION          VALUE
      0     4        (object header)      82 ff f7 d5 (10000010 11111111 11110111 11010101) (-705167486)
      4     4        (object header)      31 02 00 00 (00110001 00000010 00000000 00000000) (561)
      8     4        (object header)      00 10 00 00 (00000000 00010000 00000000 00000000) (4096)
     12     4        (loss due to the next object alignment)
     
业务高峰期结束
main:java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION        VALUE
      0     4        (object header)    a8 f5 0f 24 (10101000 11110101 00001111 00100100) (605025704)
      4     4        (object header)    99 00 00 00 (10011001 00000000 00000000 00000000) (153)
      8     4        (object header)    00 10 00 00 (00000000 00010000 00000000 00000000) (4096)
     12     4        (loss due to the next object alignment)
退出同步代码块以后:
main:java.lang.Object 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)   00 10 00 00 (00000000 00010000 00000000 00000000) (4096)
 
这就显然就发生了重量级锁(010)到轻量级锁(000)的转换。
ps:以上测试基于jdk11,如果是jdk8,请添加jvm启动参数:-XX:BiasedLockingStartupDelay=0
C:\Users\Administrator>java -version
java version "11.0.18" 2023-01-17 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.18+9-LTS-195)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.18+9-LTS-195, mixed mode)
                


















