高并发学习-20220816-锁升级

25 篇文章 1 订阅
6 篇文章 0 订阅

1、锁升级过程理解:

前提:使用synchronized给object对象加锁。

 1、刚new出的 object对象,是没有上锁的。-- 无锁

 2、如果同一时刻只有一个线程在使用object对象 这把锁,则将从 无锁-升级为-偏向锁。object对象头markwod中会写入当前线程指针。

3、只要发生锁竞争,及同一个时刻还有其他线程在竞争这把锁,则 将从 偏向锁-升级为-轻量级锁(也叫自旋锁)。升级过程为:

        ①撤销偏向锁

        ②多个线程抢 object对象 这把锁,抢到后 object对象头markwod中会 记录 当前线程的  Lock Record 的指针。

需了解的知识点:

线程:每个线程都有一个线程栈,线程栈中会生成自己的 Lock Record对象。     

抢锁的过程:通过自旋锁 进行抢,即 CAS 操作。 (自旋比较消耗cpu)

4、轻量级锁(自旋锁)升级为重量级锁,是由jvm自己调节决定的。

2、相关说明

2.1、自旋锁什么时候升级为重量级锁?

        轻量级锁(自旋锁)什么时候升级为重量级锁,是由jvm自己调节决定的。

2.2、为什么有自旋锁还需要重量级锁?

        自旋是消耗CPU资源的,如果锁的时间长,或者自旋线程多,CPU会被大量消耗。

重量级锁有等待队列,所以拿不到锁的进入等待队列,不需要消耗CPU资源。

        重量级锁 是从cpu申请的。

2.3、偏向锁是否一定比自旋锁效率高?

        不一定,在明确知道会有多线程竞争的情况下,偏向锁肯定会涉及锁撤销,这时候直接使用自旋锁。

        JVM启动过程,会有很多线程竞争(明确),所以默认情况启动时不打开偏向锁,过一段儿时间再打开。

2.4、 默认synchronized(o) 为:00 -> 轻量级锁

        默认情况 偏向锁有个时延,默认是4秒。
        因为JVM虚拟机自己有一些默认启动的线程,里面有好多sync代码,这些sync代码启动时就知道肯定会有竞争,如果使用偏向锁,就会造成偏向锁不断的进行锁撤销和锁升级的操作,效率较低。

-- 设置偏向锁的延迟时间
-XX:BiasedLockingStartupDelay=0

如果设定上述参数(即:设置偏向锁的延迟时间为0),则

        new Object () - > 101 偏向锁 ->线程ID为0 -> Anonymous BiasedLock 。
        打开偏向锁,new出来的对象,默认就是一个可偏向匿名对象101。

2.5、偏向锁如果有线程竞争

        撤销偏向锁,升级轻量级锁。
        线程在自己的线程栈生成LockRecord ,用CAS操作将markword设置为指向自己这个线程的LR的指针,设置成功者得到锁。

2.6、偏向锁 如果竞争加剧

        竞争加剧:有线程超过10次自旋, -XX:PreBlockSpin, 或者自旋线程数超过CPU核数的一半, jvm1.6之后,加入自适应自旋 Adapative Self Spinning , JVM自己控制

        升级重量级锁:-> 向操作系统申请资源,linux mutex , CPU从3级-0级系统调用,线程挂起,进入等待队列,等待操作系统的调度,然后再映射回用户空间。

 3、锁升级的过程

JDK较早的版本 OS的资源 互斥量 用户态 -> 内核态的转换 重量级 效率比较低

现代版本进行了优化

无锁 - 偏向锁 -轻量级锁(自旋锁)-重量级锁

        1、偏向锁 - markword 上记录当前线程指针,下次同一个线程加锁的时候,不需要争用,只需要判断线程指针是否同一个,所以,偏向锁,偏向加锁的第一个线程 。hashCode备份在线程栈上 线程销毁,锁降级为无锁

        2、有争用 - 锁升级为轻量级锁 - 每个线程有自己的LockRecord在自己的线程栈上,用CAS去争用markword的LR的指针,指针指向哪个线程的LR,哪个线程就拥有锁

        3、自旋超过10次,升级为重量级锁 - 如果太多线程自旋 CPU消耗过大,不如升级为重量级锁,进入等待队列(不消耗CPU)-XX:PreBlockSpin

        4、自旋锁在 JDK1.4.2 中引入,使用 -XX:+UseSpinning 来开启。JDK 6 中变为默认开启,并且引入了自适应的自旋锁(适应性自旋锁)。

        自适应自旋锁意味着自旋的时间(次数)不再固定,而是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。如果在同一个锁对象上,自旋等待刚刚成功获得过锁,并且持有锁的线程正在运行中,那么虚拟机就会认为这次自旋也是很有可能再次成功,进而它将允许自旋等待持续相对更长的时间。如果对于某个锁,自旋很少成功获得过,那在以后尝试获取这个锁时将可能省略掉自旋过程,直接阻塞线程,避免浪费处理器资源。

        偏向锁由于有锁撤销的过程revoke,会消耗系统资源,所以,在锁争用特别激烈的时候,用偏向锁未必效率高。还不如直接使用轻量级锁。

4、锁降级

锁降级是发生在GC 的过程,只被JVMThread访问,降级也就没啥意义了。所以可以简单认为锁降级不存在

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值