Java 多线程 -- 理解锁:手动实现可重入锁和不可重入锁
JDK提供的大多数内置锁都是可重入的,也就是 说,如果某个线程试图获取一个已经由它自己持有的锁时,那么这个请求会立 刻成功,并且会将这个锁的计数值加1,而当线程退出同步代码块时,计数器 将会递减,当计数值等于0时,锁释放。如果没有可重入锁的支持,在第二次 企图获得锁时将会进入死锁状态。
现实中,我们一般不会去手动实现锁,而是直接使用JDK或其他框架提供的锁,手动实现主要为了理解。
不可重入锁:
// 不可重入锁
class Lock{
// 是否占用
private boolean isLocked = false;
// 使用锁
public synchronized void lock() throws InterruptedException {
while(isLocked) {
wait();
}
isLocked = true;
}
// 释放锁
public synchronized void unlock(){
isLocked = false;
this.notify();
}
}
测试:
public class LockTest {
Lock lock = new Lock();
public void a() throws InterruptedException {
lock.lock();
b();
lock.unlock();
}
public void b() throws InterruptedException {
lock.lock();
// …业务代码
lock.unlock();
}
public static void main(String[] args) throws InterruptedException {
LockTest test = new LockTest();
test.a();
}
}
运行代码会发现出现死锁

可重入锁:
// 可重入锁
class ReLock{
// 是否占用
private boolean isLocked = false;
// 存储线程
private Thread lockedBy = null;
// 计数
private int holdCount = 0;
// 使用锁
public synchronized void lock() throws InterruptedException {
Thread t = Thread.currentThread();
while(isLocked && lockedBy != t) {
this.wait();
}
isLocked = true;
lockedBy = t;
holdCount++;
}
// 释放锁
public synchronized void unlock() {
if(Thread.currentThread() == lockedBy) {
holdCount--;
if(holdCount == 0) {
isLocked = false;
this.notify();
lockedBy = null;
}
}
}
public int getHoldCount() {
return holdCount;
}
}
测试:
public class LockTest02 {
ReLock lock = new ReLock();
public void a() throws InterruptedException {
lock.lock();
System.out.println(lock.getHoldCount());
b();
lock.unlock();
System.out.println(lock.getHoldCount());
}
public void b() throws InterruptedException {
lock.lock();
System.out.println(lock.getHoldCount());
// .....业务代码
lock.unlock();
System.out.println(lock.getHoldCount());
}
public static void main(String[] args) throws InterruptedException {
LockTest02 test = new LockTest02();
test.a();
Thread.sleep(1000);
System.out.println(test.lock.getHoldCount());
}
}
运行代码:

可重入锁通过计数方式,没有出现死锁现象。
Java 多线程 -- 理解锁:手动实现可重入锁和不可重入锁的更多相关文章
- java多线程:线程同步synchronized(不同步的问题、队列与锁),死锁的产生和解决
0.不同步的问题 并发的线程不安全问题: 多个线程同时操作同一个对象,如果控制不好,就会产生问题,叫做线程不安全. 我们来看三个比较经典的案例来说明线程不安全的问题. 0.1 订票问题 例如前面说过的 ...
- Java多线程的同步机制(synchronized)
一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在 java里边就是拿到某个同步对象的锁(一个对象只有一把锁): 如果这个时候同步对象的锁被其他线程拿走了,他(这个 ...
- Java的多线程机制系列:(四)不得不提的volatile及指令重排序(happen-before)
一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...
- Java多线程——深入重入锁ReentrantLock
简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...
- 【java多线程系列】java内存模型与指令重排序
在多线程编程中,需要处理两个最核心的问题,线程之间如何通信及线程之间如何同步,线程之间通信指的是线程之间通过何种机制交换信息,同步指的是如何控制不同线程之间操作发生的相对顺序.很多读者可能会说这还不简 ...
- Java多线程:synchronized的可重入性
从Java多线程:线程间通信之volatile与sychronized这篇文章中我们了解了synchronized的基本特性,知道了一旦有一个线程访问某个对象的synchronized修饰的方法或代码 ...
- “全栈2019”Java多线程第二十九章:可重入锁与不可重入锁详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- Java多线程系列——深入重入锁ReentrantLock
简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...
- Java 多线程 重入锁
作为关键字synchronized的替代品(或者说是增强版),重入锁是synchronized的功能扩展.在JDK 1.5的早期版本中,重入锁的性能远远好于synchronized,但从JDK 1.6 ...
随机推荐
- python之进程,线程
什么是进程(process)? 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本 ...
- Visio2013 专业版激活码和激活工具 亲测有效
Visio2013密钥 专业版:Visio Professional 2013 KEY C2FG9-N6J68-H8BTJ-BW3QX-RM3B3 2NYF6-QG2CY-9F8XC-GWMBW-29 ...
- docker 本地镜像导入导出 compose安装
docker 本地镜像导入导出 1.Docker导入本地gz镜像 [root@rocketmq-nameserver4 dev]# cat alibaba-rocketmq-3.2.6.tar.gz ...
- 实验十一 MySQLl备份与恢复1
实验十一 MySQL备份与恢复 一. 实验内容: 1. 使用SQL语句导入和导出表数据 2. 使用客户端工具备份还原数据库 3. 使用日志文件恢复数据库 二. 实验项目:学生成绩数据库 创建用于学 ...
- Q - Marriage Match IV (非重复最短路 + Spfa + 网络最大流Isap)
Q - Marriage Match IV Do not sincere non-interference. Like that show, now starvae also take part in ...
- java 第六周上机练习 04.09
1.编写一个简单程序,要求数组长度为5,静态赋值10,20,30,40,50,在控制台输出该数组的值. int [] arr= {10,20,30,40,50}; for(int i=0;i<a ...
- springboot项目下的Caused by: org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
今天遇到mybatis-puls的报错Caused by: org.apache.ibatis.binding.BindingException: Invalid bound statement (n ...
- 在.NET Core中检查证书的到期日期
在 NUnit 测试中,我需要检查证书的有效期. 下面的代码片段可用于使用自定义证书验证回调检查任何证书属性. 所有你需要做的就是在回调中读取你感兴趣的属性,这样你就可以在之后检查它们. DateTi ...
- C++不被继承的内容
C++不被继承的内容 派生类会继承基类所有的方法和变量,除了: 构造函数,析构函数 重载运算符 友元函数 注意,私有成员是被继承了的,只是无法访问.我们可以通过sizeof判断出来.下面附一张清晰的图
- 【PHP】PHP基本语法
一.什么是PHP? a) 定义:PHP就是超文本预处理器 b) 超文本:我们前边8天学习的内容其实就是超文本内容 c) 预处理器:相当于牛奶在工厂加工的过程,我们虽然不可见,但是我们 ...