【温故知新】直观看到synchronized的锁升级过程

AI 怎么说

当我问deepseek,synchronized的锁升级过程,
在这里插入图片描述
在这里插入图片描述

一探究竟

它提到可以用jol来查看对象头,很久以前用过这个:如何查看一个java对象的大小 , 那么是否有更详细的代码能演示这个过程呢? 说干就干:
引入jol依赖:

    // https://mvnrepository.com/artifact/org.openjdk.jol/jol-core
    implementation group: 'org.openjdk.jol', name: 'jol-core', version: '0.17'
 public static void main(String[] args) throws InterruptedException {
        System.out.println(VM.current().details());

        // by default 5 seconds initial delay for biased locking
        Thread.sleep(1000 * 10);

        final A a = new A();

        ClassLayout layout = ClassLayout.parseInstance(a);

        System.out.println("**** Fresh object");
        System.out.println(layout.toPrintable());

        // biased locking demo
        System.out.println("################### biased locking demo ###################");
        synchronized (a) {
            System.out.println("**** With the lock");
            System.out.println(layout.toPrintable());
        }

        System.out.println("**** After the lock");
        System.out.println(layout.toPrintable());

        // Synchronized locks upgrades
        // free -> biased( one thread enter locking) -> lightwieght (different thread , while time split it out) -> heavyweight mutex

        // lightweight locking demo
        System.out.println("################### lightweight locking demo ###################");
        A a2 = new A();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (a2) {
                    System.out.println("**** lightweight locking With the lock - Thread1 ");
                    System.out.println(ClassLayout.parseInstance(a2).toPrintable());
                }

            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // sleep much longer.
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (a2) {
                    System.out.println("**** lightweight locking With the lock - Thread2 ");
                    System.out.println(ClassLayout.parseInstance(a2).toPrintable());
                }

            }
        }).start();

        Thread.sleep(1000 * 6);

        System.out.println("################### heavyweight locking demo ###################");
        A a3 = new A();
        ExecutorService es = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            es.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (a3) {
                        System.out.println("**** heavyweight locking With the lock -  " + Thread.currentThread().getName());
                        System.out.println(ClassLayout.parseInstance(a3).toPrintable());
                    }
                }
            });
        }
        es.shutdown();
        es.awaitTermination(1, TimeUnit.MINUTES);

        // final tasks
        // wait all done
        Thread.sleep(1000 * 10);
    }

在上面的代码中分别演示了从free -> biased locking -> light weight locking -> heavyweight locking. 查看输出可以进一步验证:

1、无锁:biasable 表示

Test$A object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000000000005 (biasable; age: 0)
  8   4        (object header: class)    0xf80155ab
 12   4        (object alignment gap)    
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

2、偏向锁, 单线程的多次获取:biased 表示

################### biased locking demo ###################
**** With the lock
Test$A object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000022d09abb805 (biased: 0x000000008b426aee; epoch: 0; age: 0)
  8   4        (object header: class)    0xf80155ab
 12   4        (object alignment gap)    
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

**** After the lock
Test$A object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000022d09abb805 (biased: 0x000000008b426aee; epoch: 0; age: 0)
  8   4        (object header: class)    0xf80155ab
 12   4        (object alignment gap)    
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

3、轻度锁,多线程的错开时间使用,thin lock 表示

################### lightweight locking demo ###################
**** lightweight locking With the lock - Thread1 
Test$A object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000022d30252005 (biased: 0x000000008b4c0948; epoch: 0; age: 0)
  8   4        (object header: class)    0xf80155ab
 12   4        (object alignment gap)    
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

**** lightweight locking With the lock - Thread2 
Test$A object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000005a776fef68 (thin lock: 0x0000005a776fef68)
  8   4        (object header: class)    0xf80155ab
 12   4        (object alignment gap)    
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

4、重度锁,高竞争,fat lock 表示

################### heavyweight locking demo ###################
**** heavyweight locking With the lock -  pool-1-thread-7
Test$A object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000022d2dc624da (fat lock: 0x0000022d2dc624da)
  8   4        (object header: class)    0xf80155ab
 12   4        (object alignment gap)    
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

**** heavyweight locking With the lock -  pool-1-thread-6
Test$A object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000022d2dc624da (fat lock: 0x0000022d2dc624da)
  8   4        (object header: class)    0xf80155ab
 12   4        (object alignment gap)    
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

**** heavyweight locking With the lock -  pool-1-thread-4
Test$A object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000022d2dc624da (fat lock: 0x0000022d2dc624da)
  8   4        (object header: class)    0xf80155ab
 12   4        (object alignment gap)    
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total