java锁之偏向锁、轻量级、重量级锁

最近在恶补知识,也是发现了,知识看一遍理解不完全,也记不住,是需要多次重复,多次熟悉,每次都有新发现。

java锁分为4中:无锁状态、偏向锁、轻量级锁、重量级锁,四种锁只能升级不能降级,竞争程度也随之升级。

1,无锁状态,顾名思义;

2,偏向锁,HotSpot的作者经过研究发现,多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得。因此为了让线程获得锁的代价降低,因此有了偏向锁。太繁琐了,简而言之,一个叫做java对象的东西,他内部有各种各样(其实就3个)的字段:

a,Mark Word(与锁、hasCode有关);

b,Class Metadata Address(存储到对象类型的数据的指针);

c,Array Length(如果对象是数组,就是数组的长度)。

java对象的Mark down里存着某个线程的id,这个是偏向锁,如果没有其他的线程来竞争,那加锁和解锁的过程只是测试一下对象头的Mark down里是否存储着该线程的偏向锁。那如果这个时候有另外的线程过来竞争了,偏向锁就要撤销了。

3,轻量级锁,如果某个对象是多个线程经常竞争的话,那就是轻量级锁了,这时候,单单靠对象头里设置一个线程的id已经无法解决问题了。这时候,需要另外一种方式:线程在栈桢中创建一块空间,把对象头的Mark down信息复制过来,官方成为Displaced Mark Down。

加锁的时候,线程尝试使用CAS将对象头的Mark Down替换为锁记录的指针,如果成功了,则就获取锁成功了,否则,就表示有其他的线程也竞争,此时,当前线程就会使用自旋来获取锁(自旋?左旋?右旋?还没来得及搞清楚,等后续搞清楚再来)。

解锁的时候,会使用原子的CAS将当前线程中的Displaced Mark Down替换回到对象的对象头里,还原成它原来的样子,如果成功,就表示竞争没有发生,如果失败,就表示当前的锁,存在着竞争,锁就会膨胀为重量级锁。一旦锁升级为重量级锁,其他线程试图获取锁时,都会被阻塞住,当持有锁的线程释放锁之后,会唤醒这些线程,被唤醒的线程就会进行新一轮的夺琐之争。

 

锁的优点和缺点对比
优点缺点适用场景
偏向锁加锁和解锁不需要额外的消耗,和执行非同步方法相比,仅存在纳秒级差距如果线程存在锁竞争,会带来额外的锁撤销和损耗适用于只有一个线程访问同步块的场景
轻量级锁竞争的线程不会阻塞,提高了程序的响应速度如果始终得不到锁竞争的线程,使用自旋会消耗CPU追求响应时间,同步块执行速度非常快
重量级锁线程竞争不使用自旋,不会消耗CPU线程阻塞,响应时间缓慢追求吞吐量,同步块执行速度较长

 

 

 

 

 

 

 

 锁,就是这些,有些能锁住人,却锁不住心;有些能锁住代码,却锁不住雪崩。

以上来自:《Java并发编程的艺术》总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值