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 多线程 -- 理解锁:手动实现可重入锁和不可重入锁的更多相关文章

  1. java多线程:线程同步synchronized(不同步的问题、队列与锁),死锁的产生和解决

    0.不同步的问题 并发的线程不安全问题: 多个线程同时操作同一个对象,如果控制不好,就会产生问题,叫做线程不安全. 我们来看三个比较经典的案例来说明线程不安全的问题. 0.1 订票问题 例如前面说过的 ...

  2. Java多线程的同步机制(synchronized)

    一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在 java里边就是拿到某个同步对象的锁(一个对象只有一把锁): 如果这个时候同步对象的锁被其他线程拿走了,他(这个 ...

  3. Java的多线程机制系列:(四)不得不提的volatile及指令重排序(happen-before)

    一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...

  4. Java多线程——深入重入锁ReentrantLock

    简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...

  5. 【java多线程系列】java内存模型与指令重排序

    在多线程编程中,需要处理两个最核心的问题,线程之间如何通信及线程之间如何同步,线程之间通信指的是线程之间通过何种机制交换信息,同步指的是如何控制不同线程之间操作发生的相对顺序.很多读者可能会说这还不简 ...

  6. Java多线程:synchronized的可重入性

    从Java多线程:线程间通信之volatile与sychronized这篇文章中我们了解了synchronized的基本特性,知道了一旦有一个线程访问某个对象的synchronized修饰的方法或代码 ...

  7. “全栈2019”Java多线程第二十九章:可重入锁与不可重入锁详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  8. Java多线程系列——深入重入锁ReentrantLock

    简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...

  9. Java 多线程 重入锁

    作为关键字synchronized的替代品(或者说是增强版),重入锁是synchronized的功能扩展.在JDK 1.5的早期版本中,重入锁的性能远远好于synchronized,但从JDK 1.6 ...

随机推荐

  1. Fiddler抓取数据包分析案例

    案例:利用Fiddler抓取苏宁易购网站数据包分析 抓包软件:Fiddler4 请求名字:www.suning.com 详细内容: 一.了解数据包区域的字段含义 图1数据包区域 #:顺序号,按照抓包的 ...

  2. 《Mathematical Analysis of Algorithms》中有关“选择第t大的数”的算法分析

    开头废话 这个问题是Donald.E.Knuth在他发表的论文Mathematical Analysis of Algorithms中提到的,这里对他的算法分析过程给出了更详细的解释. 问题描述: 给 ...

  3. [POI2014][树形DP]FarmCraft

    题目 In a village called Byteville, there are houses connected with N-1 roads. For each pair of houses ...

  4. Day19-apache

    HTTPD(俗称apache) 简介:目前来说,Linuxweb服务器主要用apache与nginx. 1.web服务器的输入/输出结构: 单线程I/O结构 多线程I/O结构 复用的I/O结构,单个线 ...

  5. 线程间交换数据的Exchanger

    作者:Steven1997 链接:https://www.jianshu.com/p/9b59829fb191 来源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处. Exc ...

  6. 一款基于SVM算法的分布式法律助手

    一. 项目简介 与 使用说明 体验网站(适配手机端): http://www.zhuchangwu.com 项目基于 Spring Cloud .Vue 构建,平台针对需要维权的用户而设计,主要提供如 ...

  7. B 基因改造

    时间限制 : - MS   空间限制 : - KB  问题描述 "人类智慧的冰峰,只有萌萌哒的我寂寞地守望."--TBTB正走在改造人类智慧基因的路上.TB发现人类智慧基因一点也不 ...

  8. python通俗讲解闭包

    通俗理解闭包 先来看看什么是闭包吧 闭包是引用了自由变量的函数.这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外.所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合 ...

  9. Android 添加键值并上报从驱动到上层

    转载:https://blog.csdn.net/weixin_43854010/article/details/94390803 Android 添加键值并上报从驱动到上层 平台 :RK3288 O ...

  10. Java第三十五天,用JDBC操作MySQL数据库(一),基础入门

    一.JDBC的概念 Java DataBase Connectivity 从字面意思我们也不难理解,就是用Java语言连接数据库的意思 JDBC定义了Java语言操作所有关系型数据库的规则(接口).即 ...