

描述一下锁的四种状态及升级过程? - 程序员Forlan
source link: https://www.cnblogs.com/huozhonghun/p/17185298.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

1、锁的四种状态
无锁、偏向锁、轻量级锁、重量级锁
2、Java对象头描述
以下为32位对象头描述


3、锁的升级过程(Synchronized加锁/膨胀流程)
1)简单过程如下图

2)详细过程
当线程访问同步代码块时,首先判断当前锁状态是否为可偏向状态(对象头中偏向锁=1,锁标志=01)在JDK1.6以上默认开启,开启后程序启动几秒后才会被激活
(1)偏向锁
如果是可偏向状态,检查MarkWord存储的是否是当前线程ID
- 是,获得偏向锁,执行同步代码块
- 不是,CAS操作竞争锁,替换线程ID
- 替换成功,MarkWord的线程ID设置为当前线程ID(线程复用),执行同步代码块
- 替换失败,锁撤销,升级为轻量级锁
同一类对象多次撤销升级达到阈值20,则偏向锁认为,后面的锁需要重新偏向新的线程(批量重偏向)
如果阈值达到40次,则偏向锁认为偏向锁撤销过于频繁,后面直接使用轻量级锁
(2)轻量级锁
升级为轻量级锁的情况
- 如果不是可偏向状态,直接升级为轻量级锁
- 偏向锁撤销次数过多
加锁时,会在当前线程栈帧中划出一块空间,作为该锁记录,并且将锁对象MarkWord复制到该锁记录中,CAS操作将MarkWord更新为该锁记录的指针,锁记录中的owner指针指向对象头的MarkWord。
- 更新成功,MarkWord锁标志位为00,表示轻量级锁状态
- 更新失败,检查锁对象MarkWord是否指向当前线程栈帧中的锁记录
- 是,表示锁重入,在当前线程栈帧中锁记录+1
- 否,自旋等待(默认10次),等待次数达到阈值,升级为重量级锁
(3)重量级锁
升级为重量级锁的情况
- 竞争加剧,CAS自旋到一定次数升级为重量级锁
- 自旋线程数超过CPU核数的一半, 1.6之后,加入自适应自旋Adapative Self Spinning,JVM自己控制
获取锁成功,进入EntryList(获取锁的缓冲区、入口)
- 在调用wait方法后,会进入等待唤醒队列(WaitSet)等待
- 在调用notify方法后,则可能进入EntryList
获取锁失败,进入一个等待拿锁队列(cxq)等待
具体重量级锁加锁过程:
1、分配⼀个ObjectMonitor对象,把MarkWord锁标志置为‘10’,然后MarkWord存储指向ObjectMonitor对象的指针。ObjectMonitor对象有两个队列和⼀个指针,每个需要获取锁的线程都包装成ObjectWaiter对象
2、多个线程同时执行同⼀段同步代码时,ObjectWaiter先进⼊EntryList队列,当某个线程获取到对象的monitor以后进⼊Owner区域,并把monitor中的owner变量设置为当前线程,同时monitor中的计数器count+1
说明:
monitor:每个Java对象都有一把锁,称为内部锁或monitor锁
owner,指向的是当前获得线程的地址,用来判断当前锁是被哪个线程持有
1)synchronized效率低?
用户态:偏向锁、轻量级锁
内核态:重量级锁
首先来了解下synchronized重量级锁实现原理?
通过对象内部的一个叫做监视器锁(monitor)来实现的,监视器锁本质又是依赖于底层的操作系统的 Mutex Lock(互斥锁)来实现的。而操作系统实现线程之间的切换需要从用户态转换到核心态,这个成本非常高。
在JDK6以前,只有重量级锁,阻塞或唤醒一个Java线程需要操作系统切换CPU状态来完成,这种状态切换需要耗费处理器时间。
在JDK6中,为了提高性能,引入了偏向锁和轻量级锁。
2)为什么要有偏向锁?
大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,为了减少线程获得锁的代价,所以引入了偏向锁
3)为什么要有重量级锁?
自旋锁消耗CPU资源,重量级锁有等待队列,不会消耗CPU资源
4)偏向锁是否一定比自旋锁效率高?
不一定,在多线程竞争情况下,偏向锁会涉及锁撤销,这时候应该直接使用自旋锁
5)锁重入
重入次数必须记录,才能知道要解锁几次
- 轻量级锁,记录在线程栈,每插入一次,LockRecord+1
- 重量级锁,记录在ObjectMonitor字段上
6)Hopspot对象头就是MarkWord?
不是的,Hopspot对象头主要包括两部分数据:MarkWord(标记字段) 和 classPointer(类指针)
7)锁可以降级?
不行的,是一个不可逆的过程,主要是为了提高获得锁和释放锁的效率
8)锁对比,适用场景?
偏向锁:适用于一个线程,不会有锁消耗,锁撤销
轻量级锁:适用于多个线程竞争,但同步代码块执行快的情况下,因为自旋会消耗CPU
重量级锁:适用于多个线程竞争,但同步代码块执行慢的情况下,不消耗CPU,可以提高吞吐量
Recommend
-
56
案例 一个管理后台的bug,把操作记录中的操作员姓名,写成了该操作员的id。原因是修改了一个返回操作人姓名的函数,返回了操作人的id。但是还有其他地方也用这个函数,导致其他地方把姓名字段填写成了操作员的id。...
-
30
一、前言 锁的状态总共有四种,级别由低到高依次为: 无锁、偏向锁、轻量级锁、重量级锁 ,这四种锁状态分别代表什么,为什么会有锁升级?其实在 JDK 1.6之前, synchronized 还是一个重量级锁 ,是一个效率...
-
5
是否能够详细描述一下JVM如何去回收元数据空间的内存控制机制?因为采用的是本地内存 - OSCHINA - 中文开源技术交流社区
-
7
← 美国押注默克(Merck)的口服抗病毒药,签约12亿美刀今日好价:卡西欧小空霸 →majer @ 2021...
-
3
如何设置 input 框为不可编辑状态 (四种方法)发布于 8 月 23 日方法 一 : readonly 规定输入字段为只读可复制,但是,用户可以使用Tab键切...
-
6
免费!Windows 11 正式版来了,这四种方式快速升级...老电脑也能用-极果 免费!Windows 11 正式版来了,这四种方式快速升...
-
4
百图画鸿蒙 | 一图一主干 如果把鸿蒙比作人,百图目的是要画出其骨骼系统。 百图系列每张图都是心血之作,耗时甚大,能用一张就绝不用两张,所以会画的比较复杂,高清图会很大,可在公号中回复 百图 获取3...
-
4
转眼2022年已经过去四分之一,魔幻的2022年,让不少人真正的体会到了“夹缝中生存”的辛酸。 不完全统计一下大致可以分为一下...
-
4
#软件改变生活# iOS16升级描述文件下载,我们一起体验新的改变!
-
3
欧雷说:「后面描述的那种状态,听起来像是“入定”。突然想起一个词——天人合一。」 欧雷说:「后面描述的那种状态,听起来像是“入定”。突然想起一个词——天人合一。」
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK