Java并发 | 17.[锁机制] 重量级锁(Monitor+自旋锁)

1. 对象头

对象 = 对象头 + 对象的成员变量

2. Monitor概述

Monitor译为「监视器」或「管程」,此类对象由操作系统提供,每个Java对象都可以关联一个 Monitor 对象。

Java对象与Monitor对象是一一对应的。如果使用 synchronized 给一个Java对象上了锁(重量级锁),该Java对象头中的 MarkWord 对应的指针就会指向一个唯一的 Monitor 对象。

Java对象与Monitor对象

Monitor中有三个变量,分别是Owner、EntryList和WaitSet,本文暂不讨论WaitSet

  • [Owner] 当某个线程 拥有锁,那么 Owner 就会指向该线程,表示 只允许该线程执行代码块
  • [EntryList] 链表结构,当线程 没能抢到锁,那么该线程就会被加入到EntryList中。待拥有锁的线程执行完毕,就会根据JVM底层的算法机制,唤醒其中的一个线程并使之成为新的 Owner。

3. 自旋锁(自适应自旋锁)概述

自旋锁是指:若线程A获取锁失败,那它并不会立即阻塞,也不会放弃CPU执行时间,而是循环去 争抢锁(默认10次),期间若成功抢到锁则正常执行,若仍未抢到则宣告争抢失败,随即进行相关的操作(阻塞、进入EntryList)。

而自适应自旋锁是指争抢的时间和次数不再固定,而是根据过往的竞争情况不断调整,自适应地确定更合适的争抢时间和次数。

[为什么自旋] 因为进入休眠后再次唤醒将进行上下文切换,该操作相对而言更消耗性能,因此要尽可能让该线程抢到锁;

[什么情况下适合自旋] 仅适合多核CPU时,如果是单核CPU则没有任何意义。

4. 重量级锁(Monitor + 自旋锁)

4.1. 适用范围

  • JDK1.6以前;
  • 竞争激烈(对象锁经常会被多个线程争抢)

4.2. 底层机制

jdk1.6以前,被 synchronized 锁住的对象将会上「重量级锁」。

首先向操作系统申请一个 Monitor 对象,且obj对象头中 MarkWord 的指针将会指向这个 Monitor 对象。

  • [第一个获取锁的线程] 当第一个线程t1发现 Monitor 的 Owner 为null,则将 Owner 指向t1(拥有锁);
  • [其他想争抢锁的线程] 若其他的线程t2发现 Monitor 的 Owner 不为null,那t2会循环 争抢锁自旋锁),若超过次数后依旧没抢到锁(默认10次),则会进入到 EntryList 中并进入 BLOCKED 状态。
  • [执行完毕] 若 Owner 对应的线程执行完毕,Owner 指针便会断开(释放锁),同时根据JVM底层算法唤醒其中一个线程,使之成为新的 Owner。

多线程执行synchronized代码时

参考资料

[视频] 04.026-Monitor-对象头

[视频] 04.027-Monitor-工作原理

[文章] 从偏向锁是如何升级到重量级锁的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值