Java SE 1.6 为了减少获得锁和释放锁带来的性能消耗,引入了偏向锁和轻量级锁;在Java SE 1.6 中,锁共有4种状态,级别从底到高依次是:无锁状态、偏向锁状态、轻量级锁和重量级锁状态,这几种状态会随着竞争情况加剧逐渐升级。锁可以升级但不能降级。

1.偏向锁

HotSpot的作者经过研究发现,大多数情况下,锁不仅存在多线程竞争,而且总是由同一线程多次获得,为了让线程获得锁的代价更低而引入了偏向锁。

(1)偏向锁的获取

注意:当JVM启动了偏向锁模式(Java 6和Java 7里是默认启动的),新创建对象的Mark Word中的ThreadID为0,说明此对象处于偏向锁状态(但未偏向任何线程),也叫作匿名偏向锁状态。

  1. 线程A第一次访问同步代码块时,先检查对象头Mark Word中锁标志位是否为01,依此判断此时对象是否处于无锁状态或者偏向锁状态;

  2. 若锁标志位是为01,然后判断偏向锁的标识是否为1:
        2.1 如果不是,则进入轻量级锁逻辑(使用CAS竞争锁)(注意:此时不是使用CAS尝试获取偏向锁,而是直接升级为轻量级锁;原因是:当偏向锁的标识为0时,表明偏向锁在此对象上被禁用,禁用原因可能是JVM关闭了偏向锁模式,或该类刚经历过bulk revocation,等等。所以应该入轻量级锁逻辑);
        2.2 如果是1,表明此对象是偏向锁状态,则进行下一步流程。

  3. 判断是偏向锁时,检查对象头Mark Word中记录的ThreadID是否是当前线程A的ID:
        3.1 如果是,则表明当前线程A已经获得过该对象锁,以后线程A进入同步代码块时,不需要CAS进行加锁,只会往当前线程A的栈中添加一条Displaced Mark Word为空的Lock Record,用来统计重入的次数。如下图。
        3.2 如果不是,则进行CAS操作,尝试将当前线程A的ID替换进Mark Word;
          3.2.1 .如果当前对象锁的ThreadID为0(匿名偏向锁状态),则会替换成功(将Mark Word中的Thread id由匿名0改成当前线程A的ID,在当前线程A栈中找到内存地址最高的可用Lock Record,将线程A的ID存入),获得到锁,执行同步代码块。
          3.2.2 .如果当前对象锁的ThreadID不为0,即该对象锁已经被其他线程B占用了,则会替换失败,开始进行偏向锁撤销。这也是偏向锁的特点,一旦出现线程竞争,就会撤销偏向锁。

(2)偏向锁的撤销

  1. 偏向锁的撤销需要等待全局安全点(safe point,代表了一个状态,在该状态下所有线程都是暂停的,stop-the-world),到达全局安全点后,持有偏向锁的线程B也被暂停了。
  2. 检查持有偏向锁的线程B的状态(会遍历当前JVM的所有线程,如果能找到线程B,则说明偏向的线程B还存活着):
        5.1 如果线程还存活,则检查线程是否还在执行同步代码块中的代码:
          5.1.1 如果是,则把该偏向锁升级为轻量级锁,且原持有偏向锁的线程B继续获得该轻量级锁。
        5.2 如果线程未存活,或线程未在执行同步代码块中的代码,则进行校验是否允许重偏向:
          5.2.1 如果不允许重偏向,则将Mark Word设置为无锁状态(未锁定不可偏向状态),然后升级为轻量级锁,进行CAS竞争锁。
          5.2.2 如果允许重偏向,设置为匿名偏向锁状态(即线程B释放偏向锁)。当唤醒线程后,进行CAS将偏向锁重新指向线程A(在对象头和线程栈帧的锁记录中存储当前线程ID)。
  3. 唤醒暂停的线程,从安全点继续执行代码。

补充: 每次进入同步块(即执行monitorenter)的时候都会以从高往低的顺序在栈中找到第一个可用的Lock Record,并设置偏向线程ID;每次解锁(即执行monitorexit)的时候都会从最低的一个Lock Record移除。所以如果能找到对应的Lock Record说明偏向的线程还在执行同步代码块中的代码。

下图为当对象所处于偏向锁时,当前线程重入3次,线程栈帧中Lock Record记录:

偏向锁的撤销
偏向锁
synchronized原理和偏向锁、轻量级锁、重量级锁的升级过程

偏向锁的获取和撤销详解相关推荐

  1. 偏向锁的获取和撤销逻辑

    1. 首先获取锁 对象的Markword,判断是否处于可偏向状态.(biased_lock=1.且ThreadId为空) 2. 如果是可偏向状态,则通过CAS操作,把当前线程的ID写入到MarkWor ...

  2. 【正本清源】Synchronized 源码全解之偏向锁的获取(基于 Openjdk12)

    文章目录 BasicObjectLock BasicLock oopDesc markOopDesc 偏向锁 偏向锁的获取 monitorenter 源码验证(bytecodeInterpreter. ...

  3. java的markword_【转帖】Java工具结构与锁实现原理及MarkWord详解

    Java工具结构与锁实现原理及MarkWord详解 https://www.pianshen.com/article/2382167638/ 我们都知道,Java工具存储在堆(Heap)内存.那么一个 ...

  4. php get 返回源码,php源码 fsockopen获取网页内容实例详解

    PHP fsockopen函数说明: Open Internet or Unix domain socket connection(打开套接字链接) Initiates a socket connec ...

  5. crashdumpandroid_Android 中Crash时如何获取异常信息详解及实例

    Android 中Crash时如何获取异常信息详解 前言: 大家都知道,Android应用不可避免的会发生crash,无论你的程序写的多完美,总是无法完全避免crash的发生,可能是由于Android ...

  6. 转载 雨松mono Unity获取游戏对象详解(来自我的长微博)

    Unity获取游戏对象详解(来自我的长微博) 转载 自 雨松mono 本文固定链接: http://www.xuanyusong.com/archives/2768 转载请注明: 雨松MOMO 201 ...

  7. mysql某个表被行锁了_MySQL 行锁和表锁的含义及区别详解

    一.前言 对于行锁和表锁的含义区别,在面试中应该是高频出现的,我们应该对MySQL中的锁有一个系统的认识,更详细的需要自行查阅资料,本篇为概括性的总结回答. MySQL常用引擎有MyISAM和Inno ...

  8. java8 方法引用详解_Java8中如何通过方法引用获取属性名详解

    前言 在我们开发过程中常常有一个需求,就是要知道实体类中Getter方法对应的属性名称(Field Name),例如实体类属性到数据库字段的映射,我们常常是硬编码指定 属性名,这种硬编码有两个缺点. ...

  9. 世界树服务器bug位置,四叶草剧场世界树bug怎么获得 世界树bug神器获取位置图文详解...

    核心提示:四叶草剧场世界树bug怎么获得?在四叶草剧场的游戏中,世界树的爬塔挑战是最近玩家们正在参与的,不少玩家不知道BUG神器在哪一层怎么获得,接下来小编就为大家详细的介绍一下四叶草剧场世界树bug ...

最新文章

  1. Python之pandas-profiling:pandas-profiling库的简介、安装、使用方法之详细攻略
  2. java awt table_java.awt.image 类 LookupTable - Java 中文参考手册
  3. class vue 添加图片_vue+element 添加图片组件
  4. AGC018F. Two Trees
  5. post url 后面跟参数_都2019年了,还问GET和POST的区别
  6. Cakephp 创建无模型的Controller
  7. 最长递增子序列 两种做法
  8. 串口转WIFI模块通信
  9. 移动硬盘RAW格式,无法识别读取
  10. 高通8953内核模块签名问题解决方法
  11. 编程导师Ivor Horton新作《Java 7入门经典》即将出版
  12. 我的足迹(Appinventor练习)
  13. 引用与引用作为函数的参数
  14. 国产RY8122 18V 2A 500KHz同步降压稳压芯片
  15. (附源码)记账微信小程序 毕业设计180815
  16. {__ob__: observer}取值报错问题
  17. git_error:src refspec dev does not match any
  18. 机器学习cae_关于CAE 仿真对HPC需求的迷思-Part 1
  19. 某电商网站的数据库设计(2)——商品销售相关数据表的设计
  20. windows PR提权

热门文章

  1. flume学习(十一):如何使用Spooling Directory Source
  2. 鄂汇办服务器处理用户信息失败,登录交管网显示获取用户信息失败
  3. 仿QQ相册RecyclerView滑动选中
  4. 关于HML要玩物联网这件事 之 CC3200 TCP Client
  5. 微信公众号/微信小程序获取用户信息以及推送微信模版消息_MQ
  6. 软件自动化测试可行性分析,基于 AI 的软件自动化测试思考与实践—kylinTOP 测试与监控平台...
  7. Lammps切削过程实现及工件表面识别
  8. win7资源服务器未响应,Win7资源管理器未响应怎么办 试试这个方法 - 驱动管家
  9. 韩国KOBA蓄电池 全系列电池供应
  10. python 读取txt函数总结