这三种锁是指锁的状态,并且是专门针对Synchronized关键字。JDK 1.6 为了减少"重量级锁"的性能消耗,引入了“偏向锁”和“轻量级锁”,锁一共拥有4种状态:无锁状态、偏向锁、轻量级锁、重量级锁。锁状态是通过对象头的Mark Word来进行标记的:

锁可以升级但不能降级,意味着偏向锁升级成轻量级锁后不能降级成偏向锁,这种锁升级却不能降级的策略,是为了提高获得锁和释放锁的效率

  1. 重量级锁:依赖于底层操作系统的Mutex Lock,线程会被阻塞住

    • 缺点:加锁和解锁需要从用户态切换到内核态,性能消耗较大
  2. 轻量级锁:基于重量级锁进行了优化(避免上下文切换,提高了性能),它假设多线程竞争是互相错开的,不会发生线程阻塞,呢么上下文切换就是多余的
    • 第一个特点:采用了CAS操作加锁和解锁,由于轻量级锁的锁记录(Lock Record)是存放在对象头和线程空间里的,因此加锁和解锁不需要上下文切换,性能消耗较小
    • 第二个特点:一旦发生多线程竞争,首先基于“自旋锁”思想,自旋CPU循环等待一段时间,不会发生上下文切换,如果还是无法获得锁,就将锁升级为重量级锁
  3. 偏向锁:基于轻量级锁进行了优化(减少多次的加锁和解锁,提高了性能),它假设整个过程只有一个线程获得锁,呢么多次的加锁和解锁就是多余的
    • 特点:在第一次获得锁之后不会释放锁,它会一直持有锁,后续进入锁时只需检查一下锁状态和偏向线程ID是否为自己,从而省去了多次的加锁和解锁

1.偏向锁

获取锁:

  1. 检测对象头的Mark Word是否为可偏向状态(即是否为偏向锁1,锁标志位是否为01),如果不是,尝试竞争锁:尝试CAS操作将Mark Word的线程ID设置为当前线程ID,以表示线程获得锁,如果失败说明锁已被占用
  2. 若为可偏向状态,则检查线程ID是否为当前线程ID,如果是则表示当前线程已经持有锁(锁的可重入),否则说明锁已被占用
  3. 如果锁已被占用,只能撤销偏向锁为无锁状态或轻量级锁

释放锁:(偏向锁使用了一种等到竞争出现才释放锁的机制,线程是不会主动释放偏向锁的,只有当其他线程竞争偏向锁时,持有偏向锁的线程才会释放锁。这样做的好处是大大减少了加锁和解锁的次数,提升性能)

  1. 偏向锁的撤销需要等待全局安全点(在这个时间点没有正在执行的字节码),暂停拥有偏向锁的线程,检查持有偏向锁的线程是否还活着
  2. 如果线程挂了,则将对象头设置成无锁状态;如果线程仍然活着,则将对象头设置为轻量级锁(锁的升级),最终轻量级锁一定会被释放

2.轻量级锁

获取锁:

  1. 检测对象头的Mark Word是否为轻量级锁(锁标志位为00),如果不是,尝试竞争锁:JVM首先在当前线程的栈帧中建立一个锁记录(Lock Record),用于备份存储对象头的Mark Word(官方把这份拷贝加了一个Displaced前缀,称为Displaced Mark Word),然后JVM尝试CAS操作将Mark Word更新为指向Lock Record的指针,以表示线程获得锁,如果失败说明锁已被占用
  2. 若为轻量级锁,判断对象头的Mark Word是否指向当前线程的栈帧的Lock Record,如果是则表示当前线程已经持有锁(锁的可重入),否则说明锁已被占用
  3. 如果锁已被占用,当前线程便尝试自旋CPU来获取锁,自旋一定次数后轻量级锁会膨胀为重量级锁(锁标志位变成10),线程进入阻塞

释放锁:

  1. 尝试CAS操作将Displaced Mark Word中替换回对象头,如果成功,说明轻量级锁释放成功
  2. 如果CAS操作失败,说明存在锁竞争,锁已经膨胀成重量级锁,需要在释放锁的同时唤醒那些被挂起的线程

3.重量级锁

重量级锁依赖于底层操作系统的Mutex Lock,所有线程都会被阻塞住,线程之间的切换需要从用户态到内核态,切换成本非常高。

总结:锁的优缺点对比

优点 缺点 适用场景
偏向锁(Biased Lock) 加锁和解锁不需要额外的消耗,和执行非同步方法相比仅存在纳秒级的差距 如果线程间存在锁竞争,会带来额外的锁撤销 适用于只有一个线程访问
轻量级锁(Lightweight Lock) 竞争的线程不会阻塞,提高了程序的响应速度 对于得不到锁的线程,自旋会消耗CPU 追求响应时间,或者要求临界区简短,自旋不会占用CPU过久
重量级锁(Heavyweight Lock) 线程竞争不使用自旋,不会消耗CPU资源 线程阻塞,响应时间缓慢 追求吞吐量

Java锁的升级策略 偏向锁 轻量级锁 重量级锁的更多相关文章

  1. 通俗易懂 悲观锁、乐观锁、可重入锁、自旋锁、偏向锁、轻量/重量级锁、读写锁、各种锁及其Java实现!

    网上关于Java中锁的话题可以说资料相当丰富,但相关内容总感觉是一大串术语的罗列,让人云里雾里,读完就忘.本文希望能为Java新人做一篇通俗易懂的整合,旨在消除对各种各样锁的术语的恐惧感,对每种锁的底 ...

  2. 写文章 通俗易懂 悲观锁、乐观锁、可重入锁、自旋锁、偏向锁、轻量/重量级锁、读写锁、各种锁及其Java实现!

    网上关于Java中锁的话题可以说资料相当丰富,但相关内容总感觉是一大串术语的罗列,让人云里雾里,读完就忘.本文希望能为Java新人做一篇通俗易懂的整合,旨在消除对各种各样锁的术语的恐惧感,对每种锁的底 ...

  3. Synchronized用法原理和锁优化升级过程(面试)

    简介 多线程一直是面试中的重点和难点,无论你现在处于啥级别段位,对synchronized关键字的学习避免不了,这是我的心得体会.下面咱们以面试的思维来对synchronized做一个系统的描述,如果 ...

  4. JAVA对象分析之偏向锁、轻量级锁、重量级锁升级过程

    在HotSpot虚拟机里,对象在堆内存中的存储布局可以划分为三个部分: 对象头(Header) 实例数据(Instance Data) 对齐填充(Padding). 对象头 HotSpot虚拟机(后面 ...

  5. Java并发之锁升级:无锁->偏向锁->轻量级锁->重量级锁

    Java并发之锁升级:无锁->偏向锁->轻量级锁->重量级锁 对象头markword 在lock_bits为01的大前提下,只有当是否偏向锁位值为1的时候,才表明当前对象处于偏向锁定 ...

  6. java 偏向锁怎么升级为轻量级锁

    因为偏向锁,锁住对象时,会写入对象头相应的标识,我们先把对象头(官方叫法为:Mark Word)的图示如下(借用了网友的图片): 通过上面的图片,我们可以知道,对象处于偏向锁时,mark word中的 ...

  7. 【Java面试】为什么引入偏向锁、轻量级锁,介绍下升级流程

    Hi,我是Mic 一个工作了7年的粉丝来找我,他说最近被各种锁搞晕了. 比如,共享锁.排它锁.偏向锁.轻量级锁.自旋锁.重量级锁. 间隙锁.临键锁.意向锁.读写锁.乐观锁.悲观锁.表锁.行锁. 然后前 ...

  8. java 中的锁 -- 偏向锁、轻量级锁、自旋锁、重量级锁(转载)

    之前做过一个测试,详情见这篇文章<多线程 +1操作的几种实现方式,及效率对比>,当时对这个测试结果很疑惑,反复执行过多次,发现结果是一样的: 1. 单线程下synchronized效率最高 ...

  9. Java 多线程之:偏向锁,轻量级锁,重量级锁

    一:java多线程互斥,和java多线程引入偏向锁和轻量级锁的原因? --->synchronized的重量级别的锁,就是在线程运行到该代码块的时候,让程序的运行级别从用户态切换到内核态,把所有 ...

随机推荐

  1. new HttpClient().PostAsync封装参数

    var data = Encoding.UTF8.GetBytes("{ \"y\": 5, \"x\": 3}"); var conten ...

  2. 关于Android studio下V4包 KeyEventCompat 类找不到问题

    V4包 KeyEventCompat 类找不到问题   本文链接:https://blog.csdn.net/shanshan_1117/article/details/84344557 今天我把su ...

  3. 【精华】PHP网站验证码不显示的终结解决方案

    PHP网站验证码不显示,这个是个很基础的PHP问题了,不过有点时候会比较让开发者比较头疼了.很多解决方案仅仅考虑到gd2,却忽略了另外一个很重要的因素了,相信在了解本教程之后,验证码不显示基本上就不算 ...

  4. Chrome 浏览器自动填表呈现淡黄色解决

      Chrome 浏览器,当记住用户名和密码后,下次填写表单时,被记住的部分会被填充为淡黄色,有些时候不好看. 解决方式如下: input:-webkit-autofill {      -webki ...

  5. Qt编写自定义控件54-时钟仪表盘

    一.前言 这个控件没有太多的应用场景,主要就是练手,论美观的话比不上之前发过的一个图片时钟控件,所以此控件也是作为一个基础的绘制demo出现在Qt源码中,我们可以在Qt的安装目录下找到一个时钟控件的绘 ...

  6. 下载Hadoop环境的虚拟机文件

    使用的是hortonworks的hadoop环境, 下载地址:https://hortonworks.com/downloads/#

  7. 关于新小米盒子的Recovery模式如何进入

    26日下的盒子订单,经过几经波折,终于在昨天来到了我的面前,新东西到手,难免少不了一些折腾:升级系统,安装软件等.一顿折腾之后,想完全恢复到出厂设置,给盒子清一下,想进入盒子的Recovery模式,按 ...

  8. 【Leetcode_easy】697. Degree of an Array

    problem 697. Degree of an Array 题意:首先是原数组的度,其次是和原数组具有相同的度的最短子数组.那么最短子数组就相当于子数组的首末数字都是统计度的数字. solutio ...

  9. React16+配置打包目录

    在学习react的时候,肯定最终都要用脚手架,对比了手写配置webpack(比较费劲).generator-react-webpack(打不开官方文档……),最终还是选择了react官方的create ...

  10. charles 验证工具

    本文参考:charles 验证工具 验证工具/validate 验证工具 Charles可以通过发送到W3C HTML验证器,W3C CSS验证器和W3C Feed验证器来验证记录的响应. 验证报告在 ...