并发编程(十六)Synchronized锁升级-偏向锁(下)-例2

85 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第15天,点击查看活动详情

1.偏向锁竞争

假设一种情况A线程获取偏向锁,并且A线程释放锁后线程并没有死亡。B线程争抢偏向锁,此时B线程的锁状态是什么样子的? 举个例子:

public class SyncSyncLockRelease1 {
    public static void main(String[] args) throws InterruptedException {
        Object obj = new Object();
        System.out.println("====A 加锁前==="+ClassLayout.parseInstance(obj).toPrintable());
        Thread A = new Thread() {
            @SneakyThrows
            @Override
            public void run() {
                synchronized (obj) {
                    System.out.println("===A 加锁中==="+ClassLayout.parseInstance(obj).toPrintable());
                }
                Thread.sleep(2000);
            }
        };
        A.start();
        Thread.sleep(500);
        System.out.println("====B加锁前==="+ClassLayout.parseInstance(obj).toPrintable());
        Thread B = new Thread() {
            @SneakyThrows
            @Override
            public void run() {
                synchronized (obj) {
                    System.out.println("====B加锁中==="+ClassLayout.parseInstance(obj).toPrintable());
                    Thread.sleep(1000);
                }
            }
        };
        B.start();
    }
}

执行效果如下:

====A 加锁前===java.lang.Object 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)                           e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

===A 加锁中===java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           05 20 ee 18 (00000101 00100000 11101110 00011000) (418258949)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

====B加锁前===java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           05 20 ee 18 (00000101 00100000 11101110 00011000) (418258949)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

====B加锁中===java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           10 f6 5b 1b (00010000 11110110 01011011 00011011) (459011600)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

我们一块一块分析。

image.png 当程序开始执行时,A线程会先开启,由于主线程会睡眠500毫秒后才启动B线程,所以B线程还未开启,A线程执行效果,可以看到A线程此时还是偏向锁,但是未记录线程id。

image.png 当线程A进入同步代码块时,此时锁状态是偏向锁,并且记录了线程id。

image.png

当B线程开始执行,并进入同步代码块前,我们可以看到此时锁还是偏向锁,并且记录的锁id还是B线程的。

image.png 当B线程进入同步代码块时,我们可以看到,B竞争锁后,锁升级为轻量级锁,并且记录了锁记录指针。

2.总结

A线程获取偏向锁,并且A线程释放了锁,但是A线程并没有死亡还在活跃状态。B线程过来争抢,会直接升级为轻量级锁。