当前位置:网站首页>可重入锁详解(什么是可重入)
可重入锁详解(什么是可重入)
2022-08-03 12:17:00 【全栈程序员站长】
大家好,又见面了,我是你们的朋友全栈君。
可重入锁详解
概述
什么是 “可重入”,可重入就是说某个线程已经获得某个锁,可以再次获取锁而不会出现死锁。例如
package com.test.reen;
// 演示可重入锁是什么意思,可重入,就是可以重复获取相同的锁,synchronized和ReentrantLock都是可重入的
// 可重入降低了编程复杂性
public class WhatReentrant {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
synchronized (this) {
System.out.println("第1次获取锁,这个锁是:" + this);
int index = 1;
while (true) {
synchronized (this) {
System.out.println("第" + (++index) + "次获取锁,这个锁是:" + this);
}
if (index == 10) {
break;
}
}
}
}
}).start();
}
}
package com.test.reen;
import java.util.Random;
import java.util.concurrent.locks.ReentrantLock;
// 演示可重入锁是什么意思
public class WhatReentrant2 {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
new Thread(new Runnable() {
@Override
public void run() {
try {
lock.lock();
System.out.println("第1次获取锁,这个锁是:" + lock);
int index = 1;
while (true) {
try {
lock.lock();
System.out.println("第" + (++index) + "次获取锁,这个锁是:" + lock);
try {
Thread.sleep(new Random().nextInt(200));
} catch (InterruptedException e) {
e.printStackTrace();
}
if (index == 10) {
break;
}
} finally {
lock.unlock();
}
}
} finally {
lock.unlock();
}
}
}).start();
}
}
可以发现没发生死锁,可以多次获取相同的锁
可重入锁有
- synchronized
- ReentrantLock
使用ReentrantLock的注意点
ReentrantLock 和 synchronized 不一样,需要手动释放锁,所以使用 ReentrantLock的时候一定要手动释放锁,并且加锁次数和释放次数要一样
以下代码演示,加锁和释放次数不一样导致的死锁
package com.test.reen;
import java.util.Random;
import java.util.concurrent.locks.ReentrantLock;
public class WhatReentrant3 {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
new Thread(new Runnable() {
@Override
public void run() {
try {
lock.lock();
System.out.println("第1次获取锁,这个锁是:" + lock);
int index = 1;
while (true) {
try {
lock.lock();
System.out.println("第" + (++index) + "次获取锁,这个锁是:" + lock);
try {
Thread.sleep(new Random().nextInt(200));
} catch (InterruptedException e) {
e.printStackTrace();
}
if (index == 10) {
break;
}
} finally {
// lock.unlock();// 这里故意注释,实现加锁次数和释放次数不一样
}
}
} finally {
lock.unlock();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
lock.lock();
for (int i = 0; i < 20; i++) {
System.out.println("threadName:" + Thread.currentThread().getName());
try {
Thread.sleep(new Random().nextInt(200));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} finally {
lock.unlock();
}
}
}).start();
}
}
由于加锁次数和释放次数不一样,第二个线程始终无法获取到锁,导致一直在等待。
稍微改一下,在外层的finally里头释放9次,让加锁和释放次数一样,就没问题了
try {
lock.lock();
System.out.println("第1次获取锁,这个锁是:" + lock);
int index = 1;
while (true) {
try {
lock.lock();
System.out.println("第" + (++index) + "次获取锁,这个锁是:" + lock);
... 代码省略节省篇幅...
} finally {
// lock.unlock();// 这里故意注释,实现加锁次数和释放次数不一样
}
}
} finally {
lock.unlock();
// 在外层的finally里头释放9次,让加锁和释放次数一样,就没问题了
for (int i = 0; i < 9; i++) {
lock.unlock();
}
}
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/124905.html原文链接:https://javaforall.cn
边栏推荐
猜你喜欢
nacos应用
基于Sikuli GUI图像识别框架的PC客户端自动化测试实践
Image fusion SDDGAN article learning
word标尺有哪些作用
特征降维学习笔记(pca和lda)(1)
海外代购系统/代购网站怎么搭建——源码解析
【云原生 · Kubernetes】部署Kubernetes集群
nacos app
什么是分布式锁?几种分布式锁分别是怎么实现的?
After completing the interview and clearance collection of Alibaba, I successfully won the 15th Offer this year
随机推荐
ROS中编译通过但是遇到可执行文件找不到的问题
Filebeat 如何保持文件状态?
Go 语言快速入门指南: 介绍及安装
__unaligned修饰指针
PC client automation testing practice based on Sikuli GUI image recognition framework
数据库系统原理与应用教程(074)—— MySQL 练习题:操作题 141-150(十八):综合练习
Image fusion GAN-FM study notes
一文带你弄懂 CDN 技术的原理
AMS simulation
bash case用法
论文理解:“Gradient-enhanced physics-informed neural networks for forwardand inverse PDE problems“
五、函数的调用过程
bash while loop and until loop
【精品必知】Pod生命周期
基于php旅游网站管理系统获取(php毕业设计)
如何免费获得一个市全年的气象数据?降雨量气温湿度太阳辐射等等数据
YOLOv5 training data prompts No labels found, with_suffix is used, WARNING: Ignoring corrupted image and/or label appears during yolov5 training
From scratch Blazor Server (6) - authentication based on strategy
海外代购系统/代购网站怎么搭建——源码解析
博客记录生活