当前位置:网站首页>升级为重量级锁,锁重入会导致锁释放?
升级为重量级锁,锁重入会导致锁释放?
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轻量级锁 重量级锁
边栏推荐
猜你喜欢

leetcode43 字符串相乘

从底层结构开始学习FPGA(6)----分布式RAM(DRAM,Distributed RAM)

字符中的第一个唯一字符

Vim三种模式

leetcode125 Verify palindrome string

MVVM project development (commodity management system 1)

curl (7) Failed connect to localhost8080; Connection refused

Matlab simulink particle swarm optimization fuzzy pid control motor pump

信息系统项目管理师必背核心考点(五十六)配置控制委员会(CCB)的工作

响应式织梦模板园林景观类网站
随机推荐
阿里云李飞飞:中国云数据库在很多主流技术创新上已经领先国外
Causes and solutions of lock table
基于MATLAB的BP神经网络进行语音特征信号分类
LeetCode 0150. 逆波兰表达式求值
小白的0基础教程SQL: 什么是SQL 01
Induction jian hai JustFE 2022/07/29 team, I learned the efficient development summary (years)
sum of special numbers
torch
问下 mysql向pg同步多个表的话 有什么好的方案吗?
LeetCode 0150. Reverse Polish Expression Evaluation
2022.7.26 Mock Competition
深度比较两个对象是否相同
Vim三种模式
【翻译】确保云原生通信的安全:从入口到服务网及更远的地方
Jupyter shortcuts
Data organization -- singly linked list of the linear table
NIO编程
信息系统项目管理师必背核心考点(五十六)配置控制委员会(CCB)的工作
flinkcdc对mysql的date字段类型转化有什么解决思路么
"By sharing" northwestern university life service | | bytes a second interview on three sides by HR