Synchronized升级成重量级锁之后就下不来了?你错了

你好,我是 yes。

之前的一篇关于 Synchronized 的一个点,网上99%的文章都错了发了之后有很多读者私聊我,感觉打破了轻量级锁升级的一个认知。

然后有一位读者的留言倒是提醒到我还有一个点,关于 Synchronized 的这个点,可能很多人的认识也是错误的

其实以前我的认识也是错误的,直至去年和另一位号主安琪拉讨论的时候才意识到这个问题。

我们都知道 synchronized 的锁升级,也听过锁升级之后不会降级,所以理所当然的认为当一个锁升级为重量级锁之后,任何线程再来争抢之后会走重量级锁的逻辑。

不会再从无锁到偏向锁到轻量级锁再到重量级锁。

那事实是怎样的呢?这篇咱们不看源码,直接整结果。

我们直接看锁对象的锁标志来判断。

直接上实验代码。


代码非常简单,先看下无锁的对象布局,然后多线程争抢此时应该是重量级锁,然后 sleep 等待所有线程执行完毕释放锁,然后再看看此时的锁布局。

最后再加一次锁看看对象布局。

这里有个注意点

1.8 的偏向锁是会延迟生效的,得在 JVM 启动 4 秒后生效,通过 -XX:BiasedLockingStartupDelay=0关闭偏向锁延迟

这边我没搞这个参数,因为不是重点,所以等下结果里面不会有偏向锁。

上结果!

在这里插入图片描述

结果显而易见,初始是无锁的。

然后4个线程同时竞争变成了重量级锁。

4个线程执行完毕之后,锁对象变成了无锁

此时再有一个线程去争抢锁,就从无锁变成了轻量级锁

所以当重量级锁释放了之后,锁对象是无锁的!

有新的线程来竞争的话又会从轻量级锁开始!

好了,over。

现在再看看 openjdk wiki 上面的这个图,关注解锁部分。

最后

想要自己测试的话,引用一个 jol 的包即可

        <dependency>
            <groupId>org.openjdk.jol</groupId>
            <artifactId>jol-core</artifactId>
            <version>0.14</version>
        </dependency>

代码也直接拷给你们:

public class YesLockTest {

    static Object yesLock;

    public static void main(String[] args) throws InterruptedException {
        yesLock = new Object();
        System.out.println("无锁时对象布局:" + ClassLayout.parseInstance(yesLock).toPrintable());
        IntStream.rangeClosed(1,4).forEach(i->{getYesLock();});
        Thread.sleep(5000L);
        System.out.println("无竞争之后,此时的对象布局:" + ClassLayout.parseInstance(yesLock).toPrintable());
        getYesLock();//此时再来一次加锁
    }


    private static void getYesLock() {
        new Thread(() -> {
            try {
                synchronized (yesLock) {
                    System.out.println("线程[" + Thread.currentThread().getName() + "]" +
                            ":重量级锁状态对象布局:" + ClassLayout.parseInstance(yesLock).toPrintable());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }

}

我是 yes,从一点点到亿点点,欢迎在看、转发、留言,我们下篇见。

#Java#
全部评论
synchronized的锁不可降级应该是指锁在升级的过程中只可升级不可降级吧,你这竞争的线程都执行完毕的,所有锁都释放了,再次加锁的时候肯定会先从无锁开始升级啊
1 回复 分享
发布于 2021-03-09 20:45
高产!
点赞 回复 分享
发布于 2021-03-06 16:26
感谢参与【创作者计划2期·技术干货场】!欢迎更多牛油来写干货,瓜分总计20000元奖励!!技术干货场活动链接:https://www.nowcoder.com/link/czz2jsghtlq(参与奖马克杯将于每周五结算,敬请期待~)
点赞 回复 分享
发布于 2021-03-08 16:07
你这讨论的都不在一个点上,人说不会降级是只竞争过程中,你这举了个上个世纪的竞争例子结束之后来个返回无锁状态了…这不是脱裤子放屁吗?
点赞 回复 分享
发布于 2021-03-16 00:57
楼主,想问一下, 释放偏向锁的时候,对象头应该是不变的吧,之前看相关的文章都说的对象头不变。
点赞 回复 分享
发布于 2022-05-25 12:34

相关推荐

5 14 评论
分享
牛客网
牛客企业服务