Table of Contents

锁的状态

偏向锁

轻量级锁

重量级锁

三种锁的对比

参考资料


今天来讲一下偏向锁、轻量级锁、重量级锁的升级以及区别。

https://www.jianshu.com/p/9998a9db17f7

锁的状态

  • 无锁状态
  • 偏向锁状态
  • 轻量级锁状态
  • 重量级锁状态

四种状态会随着竞争的情况逐渐升级,而且是不可逆的过程,即不可降级。

要注意的是,这四种状态都不是Java语言中的锁,而是Jvm为了提高锁的获取与释放效率而做的优化(使用synchronized时)。

首先通过一个小例子来解释一下三种锁的区别:

  1. 假如家里只有一个碗,当我自己在家时,没有人会和我争碗,这时即为偏向锁状态
  2. 当我和女朋友都在家吃饭时,如果女朋友不是很饿,则她会等我吃完再用我的碗去吃饭,这就是轻量级锁状态
  3. 当我和女朋友都很饿的时候,这时候就会去争抢这唯一的一个碗(贫穷的我)吃饭,这就是重量级锁状态

偏向锁


GitHub偏向锁:https://github.com/lxhq/BRAVO

Hotspot 的作者经过以往的研究发现大多数情况下锁不仅不存在多线程竞争,而且总是由同一线程多次获得,为了让线程获得锁的代价更低而引入了偏向锁。当一个线程访问同步块并获取锁时,会在对象头和栈帧中的锁记录里存储锁偏向的线程 ID,以后该线程在进入和退出同步块时不需要花费CAS操作来加锁和解锁,而只需简单的测试一下对象头的Mark Word里是否存储着指向当前线程的偏向锁,如果测试成功,表示线程已经获得了锁,如果测试失败,则需要再测试下 Mark Word中偏向锁的标识是否设置成 1(表示当前是偏向锁),如果没有设置,则使用 CAS 竞争锁,如果设置了,则尝试使用 CAS 将对象头的偏向锁指向当前线程。

偏向锁的撤销:偏向锁使用了一种等到竞争出现才释放锁的机制,所以当其他线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁。偏向锁的撤销,需要等待全局安全点(在这个时间点上没有字节码正在执行),它会首先暂停拥有偏向锁的线程,然后检查持有偏向锁的线程是否活着,如果线程不处于活动状态,则将对象头设置成无锁状态,如果线程仍然活着,拥有偏向锁的栈会被执行,遍历偏向对象的锁记录,栈中的锁记录和对象头的Mark Word要么重新偏向于其他线程,要么恢复到无锁或者标记对象不适合作为偏向锁,最后唤醒暂停的线程。 https://zhuanlan.zhihu.com/p/108405395

偏向锁的由来:

大多数情况下,锁不存在多线程竞争,而是总是由同一线程多次获得时,为了使线程获得锁的代价更低而引入了偏向锁。

偏向锁的使用:

当线程进入和退出同步块时,需要经历几个测试步骤:

  1. 测试对象头Mark Word(默认存储对象的HashCode,分代年龄,锁标记位)里是否存储着指向当前线程的偏向锁。
  2. 若测试失败,则测试Mark Word中偏向锁标识是否设置成1(表示当前为偏向锁)
  3. 没有设置则使用CAS竞争,否则尝试使用CAS将对象头的偏向锁指向当前线程

偏向锁的撤销:

当其他线程尝试竞争偏向锁时,就会释放锁,锁的撤销,需要等待全局安全点,分为以下几个步骤:

  1. 暂停拥有偏向锁的线程,检查线程是否存活
  2. 处于非活动状态,则设置为无锁状态
  3. 存活,则重新偏向于其他线程或者恢复到无锁状态或者标记对象不适合作为偏向锁
  4. 唤醒线程

偏向锁的升级:

当有第二个线程进入同步代码块时,则升级为轻量级锁

轻量级锁


轻量级锁加锁:线程在执行同步块之前, JVM会先在当前线程的栈桢中创建用于存储锁记录的空间,并将对象头中的Mark Word复制到锁记录中,官方称为Displaced Mark Word。然后线程尝试使用 CAS 将对象头中的Mark Word替换为指向锁记录的指针。如果成功,当前线程获得锁,如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋来获取锁。如果有两条以上的线程争用同一个锁,那轻量级锁就不再有效,要膨胀为重量级锁,锁标志的状态值变为”10”,Mark Word中存储的就是指向重量级(互斥量)的指针。

如果成功使用CAS将对象头重的Mark Word替换为指向锁记录的指针,则获得锁,失败则当前线程尝试使用自旋(循环等待)来获取锁。

轻量级锁解锁:轻量级解锁时,会使用原子的 CAS 操作来将Displaced Mark Word替换回到对象头,如果成功,则表示没有竞争发生。如果失败,表示当前锁存在竞争,锁就会膨胀成重量级锁。 https://zhuanlan.zhihu.com/p/108405395

当有另一个线程与该线程同时竞争时,锁会升级为重量级锁。为了防止继续自旋,一旦升级,将无法降级。

重量级锁

重量级锁特点:

其他线程试图获取锁时,都会被阻塞,只有持有锁的线程释放锁之后才会唤醒这些线程,进行竞争。

三种锁的对比

通俗来讲就是:

  • 偏向锁:仅有一个线程进入临界区
  • 轻量级锁:多个线程交替进入临界区
  • 重量级锁:多个线程同时进入临界区

这是并发专题的第一篇博客,以后还会随时更新

参考资料

《Java并发编程的艺术》

java偏向锁,轻量级锁与重量级锁为什么会相互膨胀?

什么是偏向锁、轻量级锁、重量级锁?相关推荐

  1. synchronized锁升级之重量级锁

    目录 一.什么是重量级锁? 二.重量级锁的演示 三.重量级锁的原理 四.锁的优缺点对比 一.什么是重量级锁? 当有大量的线程都在竞争同一把锁的时候,这个时候加的锁,就是重量级锁. 这个重量级锁其实指的 ...

  2. 简单理解重量级锁、轻量级锁、偏向锁

    全文使用synchronized来说明. synchronized给对象上锁,先上偏向锁,在上轻量级锁,最后上重量级锁.上什么锁,是gvm根据竞争程度自行变换的. 重量级锁 计算机操作系统本有Moni ...

  3. java多线程之锁 -- 偏向锁、轻量级锁、自旋锁、重量级锁

    转载至:https://blog.csdn.net/zqz_zqz/article/details/70233767 之前做过一个测试,详情见这篇文章<多线程 +1操作的几种实现方式,及效率对比 ...

  4. 【Java 并发编程】线程锁机制 ( 锁的四种状态 | 无锁状态 | 偏向锁 | 轻量级锁 | 重量级锁 | 锁竞争 | 锁升级 )

    文章目录 一.悲观锁示例 ( ReentrantLock ) 二.重量级锁弊端 三.锁的四种状态 ( 无锁状态 | 偏向锁 | 轻量级锁 | 重量级锁 ) 四.锁的四种状态之间的转换 ( 无锁状态 - ...

  5. javas的四种状态 无锁状态 偏向锁状态 轻量级锁状态 重量级锁状态

    一:java多线程互斥,和java多线程引入偏向锁和轻量级锁的原因? --->synchronized是在jvm层面实现同步的一种机制.  jvm规范中可以看到synchronized在jvm里 ...

  6. Java如何避免重量级锁,Java 中锁是如何一步步膨胀的(偏向锁、轻量级锁、重量级锁)...

    文章目录 重量级锁(Mutex Lock) 偏向锁(比较 ThreadID) 偏向锁获取过程 偏向锁的释放 轻量级锁(自旋) 轻量级锁的加锁过程 轻量级锁的释放 总结 重量级锁(Mutex Lock) ...

  7. 从 class 文件 看 synchronize 锁膨胀过程(偏向锁 轻量级锁 自旋锁 重量级锁)

    大家好,我是烤鸭: 前几天看马士兵老师的并发的课,里边讲到了 synchronize 锁的膨胀过程,今天想用代码演示一下. 1.  简单介绍 关于synchronize jdk 1.5 以后的优化,由 ...

  8. 2021-06-01 深入分析偏向锁、轻量级锁和重量级锁

    目录 一 重量级锁 1.1 什么是重量级锁?重量级是怎么体现的? 1.2 重量级锁的监视器工作流程 1.2.1 线程竞争锁 1.2.2 线程锁竞争成功 1.2.3 线程竞争锁失败 1.2.4 运行中的 ...

  9. 轻量级锁_Java高级架构师-Java锁的升级策略 偏向锁 轻量级锁 重量级锁

    欢迎关注头条号:Java小野猫 这三种锁是指锁的状态,并且是专门针对Synchronized关键字.JDK 1.6 为了减少"重量级锁"的性能消耗,引入了"偏向锁&quo ...

  10. java轻量级和重量级_Java 偏向锁、轻量级锁和重量级锁

    前言 最开始听到偏向锁.轻量级锁和重量级锁的概念的时候,我还以为是 Java 中提供了相应的类库来实现的,结果了解后才发现, 这三个原来是虚拟机底层对 synchronized 代码块的不同加锁方式. ...

最新文章

  1. 译-在Python正则模式中search()和match()的区别是什么?
  2. linux安装jdk和tomcat命令
  3. helm部署SkyWalking
  4. 前端 js 非控件 使用标签打印机 打印二维码和文本_青岛Web前端(HTML5)面试题分享...
  5. Sharepoint学习笔记—DebugTroubleShooting--不同调试对象的Attach方式
  6. 选择座位html,影厅座位预览效果(css3)_html/css_WEB-ITnose
  7. [转]Struts2.3.16.1+Hibernate4.3.4+Spring4.0.2 框架整合
  8. python 网站模板_使用Python抓取模板之家的CSS模板
  9. Android Studio调试功能使用总结【转】
  10. 爬虫是后端吗_北京市互联网后端职位招聘需求分析
  11. [Study] 通过游戏学编程的网站
  12. 特别实用的几种SQL语句送给大家,让你的SQL高大上!
  13. Fiddler的安装和使用教程(详细)
  14. 手机远程访问HTML5,如何使用手机连接远程桌面?
  15. 查看Casio PDA 的物理地址 MAC (DT-X7系列)
  16. 京东架构专家分享京东架构之路
  17. ImageView显示图片控件介绍
  18. Java中的日期与时间
  19. 面试题48:最长不含重复字符的子字符串
  20. 十进制转换成二进制 (栈)

热门文章

  1. AKKA Inbox收件箱
  2. 2019.7.17东湖大数据页面三
  3. 微信小程序_(校园视)开发视频的展示页_上
  4. (转载)Socket编程基本流程实践
  5. MyEclipse在删除文件后servers报错问题解决
  6. [C#] NPOI Excel解析
  7. SQLite 增删改查
  8. eclipse各种操作汇总
  9. python在编程序网站_Python的用户登录接口编制以及实现流程图
  10. ios php mysql实例_如何用PHP/MySQL为 iOS App 写一个简单的web服务器(译) PART1