多线程——synchronized补充

本文详细解析了Java中synchronized锁的机制,包括乐观锁转为悲观锁、轻量级锁与自旋锁的使用、重量级锁的内核级操作,以及锁消除和锁粗化的优化策略。
摘要由CSDN通过智能技术生成

        基本特点

        1.开始时是乐观锁,当竞争激烈后转化为悲观锁。

        2.开始是轻量级锁实现,如果锁被持有的时间较长,就转换成重量级锁。

        3.实现轻量级锁的时候⼤概率⽤到的⾃旋锁策略
        4.是不公平锁。

        5.是可重入锁。

        6.不是读写锁。

        加锁工作过程

        synchronized的加锁过程可以分为三个阶段,偏向锁、轻量级锁、重量级锁。

        偏向锁:第一个加锁的线程,会进入偏向锁阶段。此时并不是真正的加锁,只是给锁对象增加一个标签,如果后续没有其他线程加锁,那么就不会真的加锁。采用了“能不加锁就不加锁的策略”,可以节约一部分资源。如果锁对象因为锁竞争而进入轻量级锁阶段,那么这个锁被释放后再被获取时,不会进入偏向锁阶段。

        轻量级锁:当锁处于偏向锁阶段,并且有其他线程来竞争这个锁时,锁就会进入轻量级锁阶段(自适应的自旋锁)。

        此处的轻量级锁就是通过CAS来实现。

        通过CAS检查并更新⼀块内存(⽐如null=>该线程引⽤), 如果更新成功,则认为加锁成, 如果更新失败,则认为锁被占⽤,继续⾃旋式的等待(并不放弃CPU)。

        重量级锁,如果锁在轻量级锁阶段时的竞争进一步加深,自旋锁所带来的cpu消耗会过多,那么锁就会进入重量级锁阶段。

        此处的重量级锁就是指⽤到内核提供的mutex:

        执⾏加锁操作,先进⼊内核态.在内核态判定当前锁是否已经被占⽤,如果该锁没有占⽤,则加锁成功,并切换回⽤⼾态.如果该锁被占⽤,则加锁失败.此时线程进⼊锁的等待队列,挂起.等待被操作系统唤醒.经历了⼀系列的沧海桑⽥,这个锁被其他线程释放了,操作系统也想起了这个挂起的线程,于是唤醒这个线程,尝试重新获取锁。

        其他的优化

        锁消除

        锁在使用时,编译器+JVM判断锁是否可消除.如果可以,就直接消除。还是本着“能不枷锁就不加锁”的思想来节约损耗。

        锁粗化

        当锁的代码块中执行的逻辑少时,就称锁的粒度较细,反之称为较粗。

        在使用粒度细的锁的时候,期望是释放锁后,有其他线程来获取这个锁。但可能没有其他线程来获取这个锁,那么JVM就会把这些粗度较细的锁粗化为一个大锁,避免频繁获取释放锁带来的开销。

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值