锁的优化过程


JVM 将 synchronized 锁分为 无锁、偏向锁、轻量级锁、重量级锁状态。会根据情况, 依次进行升级

在这里插入图片描述

🔎无锁

线程之间不会引发安全问题,就不用加锁


🔎偏向锁

偏向锁不是真的 “加锁”, 只是先让线程针对锁做个标记(这个过程很快)

如果代码执行过程中没有其他线程来竞争这个锁, 那么就不用加锁
如果有其他线程竞争这个锁, 那么偏向锁就会真的加锁, 变成轻量级锁

偏向锁是synchronized内部做的工作
synchronized 会针对某个对象进行加锁, 偏向锁就是先去对加锁的对象做个标记
当有其他线程竞争这个锁时, JVM就会通知 偏向锁 升级成 轻量级锁


🔎轻量级锁

轻量级锁基于自旋锁实现

自旋锁
优点: 能够第一时间拿到锁
缺点: 一直消耗CPU,做不了其他事情(忙等)

如果锁竞争过于激烈(CPU消耗过大)
那么 synchronized 就会从 轻量级锁 升级成 重量级锁


🔎重量级锁

重量级锁基于挂起等待锁实现

挂起等待锁
优点: 不再消耗大量CPU资源
缺点: 锁被释放后不能第一时间拿到锁

当 synchronized 升级成重量级锁, 就意味着线程要暂时放弃 CPU, 由内核进行后续调度


🔎其他的锁优化

🌸锁消除

锁消除是编译器做的优化手段

非必要不加锁,
编译器发现代码不会引起线程安全问题却加锁的时候, 就会把锁给取消掉

举个栗子🥝

在这里插入图片描述

StringBuffer 是内部方法里面加了锁🔒
但是上述代码并不会引起线程安全问题
所以编译器就会进行优化(锁消除)


🌸锁粗化

锁粒度
synchronized 代码块中包含代码的多少
包含的代码越多, 锁粒度就越粗
包含的代码越少, 锁粒度就越细

一般写代码时, 希望锁的粒度细(代码块中包含的代码少)
这样串行的时间就会少一些, 并发的时间就会多一些

如果某个场景中涉及到频繁的加锁, 解锁操作
编译器就会将其优化, 优化成一个更粗粒度的锁
这就是锁粗化

在这里插入图片描述
该场景中由于涉及到频繁的加锁, 解锁操作
于是编译器就将其优化成了一个更粗粒度的锁

在这里插入图片描述
一个更粗粒度的锁

举个栗子🥝

滑稽老哥去给领导汇报工作

滑稽老哥给领导打电话汇报A工作情况
汇报完毕,滑稽老哥挂断电话

滑稽老哥给领导打电话汇报B工作情况
汇报完毕,滑稽老哥挂断电话

滑稽老哥给领导打电话汇报C工作情况
汇报完毕,滑稽老哥挂断电话

滑稽老哥打电话汇报工作时, 此时如果有其他的电话打给领导, 只能阻塞等待
汇报完毕, 再次汇报时, 可能其他人也在给领导打电话, 滑稽老哥阻塞等待
滑稽老哥需要再次拨打电话汇报其他工作情况(重新竞争锁)

针对上述情况, 编译器将该操作优化成了一个更粗粒度的锁

滑稽老哥向领导依次汇报A, B, C工作情况, 而不是分别打电话进行汇报
(滑稽老哥打电话给领导, 汇报工作A, B, C的情况, 挂断电话)

🔎结尾

创作不易,如果对您有帮助,希望您能点个免费的赞👍
大家有什么不太理解的,可以私信或者评论区留言,一起加油

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值