当前位置:网站首页>升级为重量级锁,锁重入会导致锁释放?
升级为重量级锁,锁重入会导致锁释放?
2022-08-01 06:48:00 【皮皮杨233】
目录
前言

近日,看到有些文章说:“产生竞争时,轻量级锁升级为重量级锁,此时持锁线程执行 CAS 操作(锁重入) 会失败,所以将会提前释放锁”
首先,持锁线程可能连同步块都未执行完成就平白无故将锁释放掉,怎么想都不合理
接下来的实验将证明上述 “提前释放锁” 结论的错误性
实验
如何验证
锁升为重量级锁后,如果会释放锁,那么锁重入肯定会失败;所以只需验证升级之后,锁重入不会阻塞即可
流程说明
main
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
try {
// Thread0 在方法中首次获取锁
first();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
Thread.sleep(5000);
new Thread(() -> {
log.debug("---------------------------Thread1 首次尝试加锁---------------------------");
synchronized (lock){
log.debug(ClassLayout.parseInstance(lock).toPrintable());
}
}).start();
}- 创建 Thread0,执行包含获取锁操作的方法
- 主线程睡眠 5s,确保 Thread0 先执行,先获取锁,并且此时为轻量级锁
- 创建 Thread1,尝试获取锁,产生锁竞争,导致锁升级
first
static void first() throws InterruptedException {
log.debug("---------------------------Thread0 首次尝试获取锁---------------------------");
synchronized(lock){
log.debug("Thread0 首次获取锁成功!");
log.debug(ClassLayout.parseInstance(lock).toPrintable());
Thread.sleep(10000);
// 第二次获取锁(锁重入)
reentrant();
}
}- Thread0 首次获取锁,打印锁对象的对象头
- 先睡眠 10s(Thead1 在此期间被创建并尝试获取锁,导致发生锁升级)
- 然后调用 reentrant() 方法,进入该方法会再次执行一次获取锁的操作
reentrant
static void reentrant(){
log.debug("---------------------------Thread0 尝试锁重入---------------------------");
synchronized(lock){
log.debug("Thread0 锁重入成功!");
log.debug(ClassLayout.parseInstance(lock).toPrintable());
}
}- Thread0 尝试再次获取锁(锁重入)
- 若未阻塞,则会执行打印,验证了结论的错误性
- 若阻塞,代表锁已释放并被其他线程获取,说明结论是正确的
结果

- 红色框:表示 Thread0 的时间线
- 蓝色框:表示 Thread1 的时间线
- 紫色框:表示锁的状态
时间线:
第 26s 主线程创建 Thread0 并启动,然后进入 5s 睡眠;Thread0 尝试第一次获取锁,成功了,锁状态 00 代表轻量级锁,然后进入 10s 睡眠
5s 之后的第 31s,主线程创建 Thread1 并启动;Thread1 尝试第一次获取锁,由于 Thread0 还在睡眠中,并且未释放锁,此时发生锁竞争,锁升级为重量级锁;Thread1 获取锁失败,进入阻塞
10s 之后的第 36s,Thread0 执行锁重入,成功了,锁状态 10 代表已升级为重量级锁;Thread0 释放锁,Thread1 从阻塞中被唤醒,并且获取锁成功
总结
实验结果表明,即使锁已经升级为重量级锁,持锁线程执行锁重入操作并未发生阻塞,所以也就不存在释放锁一说
锁已经升级,但是持锁线程可能确实并不知情,本人猜测:在锁重入或者解锁时发现已经升级为重量级锁,并且接下来不是对锁对象的对象头执行 CAS 操作,而是对它指向的 monitor 对象中的 owner 属性执行 CAS 操作
(补充:轻量级锁,锁重入执行 CAS 操作都会失败,但是它只会生成锁记录,而不是直接释放锁)
并发编程 synchronized (五) 重量级锁、轻量级锁_皮皮杨233的博客-CSDN博客_synchronized轻量级锁 重量级锁
边栏推荐
- NUMPY
- mysql的行锁和间隙锁
- LeetCode Question of the Day (309. Best Time to Buy and Sell Stock with Cooldown)
- 阿里云李飞飞:中国云数据库在很多主流技术创新上已经领先国外
- Flip letters using string container
- Data organization -- singly linked list of the linear table
- Motion analysis and parameter optimization of crank-slider mechanism
- LeetCode 0150. 逆波兰表达式求值
- 小白的0基础教程SQL: 什么是SQL 01
- Why is the lightweight VsCode used more and more?Why eat my C drive 10G?How to Painlessly Clean VsCode Cache?Teach you how to lose weight for C drive
猜你喜欢

Windows taskbar icon abnormal solution

目标检测概述-上篇

从离线到实时对客,湖仓一体释放全量数据价值

奇葩问题 npm install 报错 gyp ERR

Induction jian hai JustFE 2022/07/29 team, I learned the efficient development summary (years)

LeetCode 0149. Maximum number of points on a line

matlab 风速模型 小波滤波

企业员工人事管理系统(数据库课设)

滚动条样式修改

leetcode125 Verify palindrome string
随机推荐
Qt Widget 项目对qml的加载实例
2022.7.27 Selected lectures on good topics
rhcsa 第四天
leetcode43 string multiplication
Matlab simulink particle swarm optimization fuzzy pid control motor pump
安装SQL Server详细教程
Jupyter shortcuts
MVVM项目开发(商品管理系统一)
leetcode43 字符串相乘
Jupyter shortcuts
基于MATLAB的BP神经网络进行语音特征信号分类
MATLAB program design and application of MATLAB 2.5
爬虫框架 Scrapy 详解
Robot growth in China
matlab wind speed model wavelet filtering
LeetCode 0149. 直线上最多的点数
ORACLE modify another user package (package)
matlab simulink 粒子群优化模糊pid控制的电机泵
仿牛客网项目总结
插入排序—直接插入排序和希尔排序