可重入锁

指在同一个线程在外层方法获取锁的时候,进入内层方法会自动获取锁。

为了避免死锁的发生,JDK 中基本都是可重入锁。

下面我们来测试一下 synchronized 和  java.util.concurrent.lock.ReentrantLock 锁的可重入性

  • 测试 synchronized 加锁 可重入性
package constxiong.concurrency.a019;/*** 测试 synchronized 加锁 可重入性* @author ConstXiong* @date 2019-09-20 15:55:27*/
public class TestSynchronizedReentrant {public static void main(String[] args) {new Thread(new SynchronizedReentrant()).start();}}class SynchronizedReentrant implements Runnable {private final Object obj = new Object();/*** 方法1,调用方法2*/public void method1() {synchronized (obj) {System.out.println(Thread.currentThread().getName() + " method1()");method2();}}/*** 方法2,打印前获取 obj 锁* 如果同一线程,锁不可重入的话,method2 需要等待 method1 释放 obj 锁*/public void method2() {synchronized (obj) {System.out.println(Thread.currentThread().getName() + " method2()");}}@Overridepublic void run() {//线程启动 执行方法1method1();}}

打印结果:

Thread-0 method1()
Thread-0 method2()
  • 测试 ReentrantLock 的可重入性
package constxiong.concurrency.a019;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** 测试 ReentrantLock 的可重入性* @author ConstXiong* @date 2019-09-20 16:24:52*/
public class TestLockReentrant {public static void main(String[] args) {new Thread(new LockReentrant()).start();}}class LockReentrant implements Runnable {private final Lock lock = new ReentrantLock();/*** 方法1,调用方法2*/public void method1() {lock.lock();try {System.out.println(Thread.currentThread().getName() + " method1()");method2();} finally {lock.unlock();}}/*** 方法2,打印前获取 obj 锁* 如果同一线程,锁不可重入的话,method2 需要等待 method1 释放 obj 锁*/public void method2() {lock.lock();try {System.out.println(Thread.currentThread().getName() + " method2()");} finally {lock.unlock();}}@Overridepublic void run() {//线程启动 执行方法1method1();}}

打印结果:

Thread-0 method1()
Thread-0 method2()
  • 测试不可重入锁

我在 JDK 中没找到可重入锁,所以考虑自己实现一下。两种方式:通过 synchronized wait notify 实现;通过 CAS + 自旋方式实现

1) synchronized wait notify 方式实现

package constxiong.concurrency.a019;/*** 不可重入锁,通过 synchronized wait notify 实现* @author ConstXiong* @date 2019-09-20 16:53:34*/
public class NonReentrantLockByWait {//是否被锁private volatile boolean locked = false;//加锁public synchronized void lock() {//当某个线程获取锁成功,其他线程进入等待状态while (locked) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}//加锁成功,locked 设置为 truelocked = true;}//释放锁public synchronized void unlock() {locked = false;notify();}}

2) 通过 CAS + 自旋 方式实现

package constxiong.concurrency.a019;import java.util.concurrent.atomic.AtomicReference;/*** 不可重入锁,通过 CAS + 自旋 实现* @author ConstXiong* @date 2019-09-20 16:53:34*/
public class NonReentrantLockByCAS {private AtomicReference<Thread> lockedThread = new AtomicReference<Thread>();public void lock() {Thread t = Thread.currentThread();//当 lockedThread 持有引用变量为 null 时,设置 lockedThread 持有引用为 当前线程变量while (!lockedThread.compareAndSet(null, t)) {//自旋,空循环,等到锁被释放}}public void unlock() {//如果是本线程锁定的,可以成功释放锁lockedThread.compareAndSet(Thread.currentThread(), null);}
}

测试类

package constxiong.concurrency.a019;/*** 测试不可重入锁* @author ConstXiong* @date 2019-09-20 18:08:55*/
public class TestLockNonReentrant{public static void main(String[] args) {new Thread(new LockNonReentrant()).start();}}class LockNonReentrant implements Runnable {//   private final NonReentrantLockByWait lock = new NonReentrantLockByWait();private final NonReentrantLockByCAS lock = new NonReentrantLockByCAS();/*** 方法1,调用方法2*/public void method1() {lock.lock();try {System.out.println(Thread.currentThread().getName() + " method1()");method2();} finally {lock.unlock();}}/*** 方法2,打印前获取 obj 锁* 如果同一线程,锁不可重入的话,method2 需要等待 method1 释放 obj 锁*/public void method2() {lock.lock();try {System.out.println(Thread.currentThread().getName() + " method2()");} finally {lock.unlock();}}@Overridepublic void run() {//线程启动 执行方法1method1();}
}

测试结果,都是在 method1,调用 method2 的时候,导致了死锁,线程一直等待或者自旋下去。

参考:

http://ifeve.com/java_lock_see4/


【Java面试题与答案】整理推荐

  • 基础与语法
  • 集合
  • 网络编程
  • 并发编程
  • Web
  • 安全
  • 设计模式
  • 框架
  • 算法与数据结构
  • 异常
  • 文件解析与生成
  • Linux
  • MySQL
  • Oracle
  • Redis
  • Dubbo

Java 中可重入锁、不可重入锁的测试相关推荐

  1. java中多线程reentlock_Java多线程系列——深入重入锁ReentrantLock

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

  2. 说说Java中原子性,可见性与指令重排序的理解

    原子性:就是读数据,处理数据,写数据 这三个步骤不能被终止,或者打断:就是不能被线程调度器中断,切换线程. 这样,才能保证,原子操作在线程切换,并行处理上保证数据地顺序累加处理. 可见性:是Jvm较为 ...

  3. java中的锁(悲观锁、乐观锁、可重入锁、不可重入锁、公平锁、非公平锁、自旋锁、阻塞锁...)

    Lock接口 1.简介.地位.作用 ① 锁是一种工具,用于控制对共享资源的访问 ② Lock和synchronized,这两个是最常见的锁,它们都可以达到线程安全的目的,但是在使用和功能上又有较大的不 ...

  4. java自适应table_【进阶之路】包罗万象——JAVA中的锁

    导言 大家好,我是练习java两年半时间的南橘,下面是我的微信,需要之前的导图或者想互相交流经验的小伙伴可以一起互相交流哦. 在Java中,我们能接触到各种各样的锁,而每种锁因其特性的不同,在不同的的 ...

  5. 图解Java中那18 把锁

    乐观锁和悲观锁 独占锁和共享锁 互斥锁和读写锁 公平锁和非公平锁 可重入锁 自旋锁 分段锁 锁升级(无锁|偏向锁|轻量级锁|重量级锁) 锁优化技术(锁粗化.锁消除) 乐观锁和悲观锁 悲观锁 悲观锁对应 ...

  6. 图解Java中的18 把锁!

    乐观锁和悲观锁 独占锁和共享锁 互斥锁和读写锁 公平锁和非公平锁 可重入锁 自旋锁 分段锁 锁升级(无锁|偏向锁|轻量级锁|重量级锁) 锁优化技术(锁粗化.锁消除) 乐观锁和悲观锁 悲观锁 悲观锁对应 ...

  7. 一文足以了解什么是 Java 中的锁

    作者 |  cxuan 责编 | Elle Java 锁分类 Java 中的锁有很多,可以按照不同的功能.种类进行分类,下面是我对 Java 中一些常用锁的分类,包括一些基本的概述 从线程是否需要对资 ...

  8. 自旋锁和互斥锁的区别 java中lock Syntronized区别

    转载自:http://blog.csdn.net/susidian/article/details/51068858 自旋锁(Spin lock) 自旋锁与互斥锁有点类似,只是自旋锁不会引起调用者睡眠 ...

  9. 图解Java中18把锁

    乐观锁和悲观锁 独占锁和共享锁 互斥锁和读写锁 公平锁和非公平锁 可重入锁 自旋锁 分段锁 锁升级(无锁|偏向锁|轻量级锁|重量级锁) 锁优化技术(锁粗化.锁消除) 乐观锁和悲观锁 悲观锁 悲观锁对应 ...

  10. Java 中的锁分类以及锁的原理

    锁分类与原理 锁的分类 锁的分类及基本概念 Java对象在内存中的布局: 锁的升级过程: 锁的本质: synchronized 与Lock 的区别: 互斥锁的原理: 1.读写锁 2.读写锁的原理 3. ...

最新文章

  1. Vue引入百度地图,如何去掉左下角的版权logo百度等信息?
  2. golang 开发常见坑
  3. oracle dataguard in-memory,Oracle 11g Dataguard 物理备库配置(一)之Duplicate配置
  4. 【数据结构与算法】之深入解析“整数反转”的求解思路与算法示例
  5. POJ - 2083 Fractal(dfs,递归画图)
  6. 7.2 伪逆和线性方程 $A\mathbf{x}=\mathbf{b}$
  7. javafx按钮设计风格_Java,JavaFX的流畅设计风格按钮,切换按钮和工具提示
  8. [html] H5播放的video视频,如何实现对视频截图?
  9. Vue 模块化开发(构建项目常用工具)
  10. 【LOJ】#2230. 「BJOI2014」大融合
  11. c盘python27文件夹可以删除嘛_C盘里的空文件夹是不是都能删除啊
  12. 使用LibreOffice的Draw取代Microsoft visio
  13. CSS 字体加粗,导致布局宽度改变怎么处理?
  14. BootStrap3 排版
  15. HDMI/DVI 显示器热插拔与检测原理(HPD)
  16. 磨金石教育摄影技能干货分享|那些酷炫的照片是怎么拍出来的?
  17. ug创建html文件,UG8.0如何创建和打开中文名称的部件
  18. 团体程序设计天梯赛--个人总结
  19. 如何让自己打计算机打字快起来,电脑快速打字的技巧
  20. 汽车SoC安全故障的自动识别(下):案例展示和指标分析

热门文章

  1. 稀少珍贵的执行力首先要知道做什么。
  2. matlab 对象属性,matlab对象属性
  3. 《惢客创业日记》2019.11.06(周三) 路遇盲人夫妻
  4. 采伐迹地和火烧迹地属于直林地_林地管理
  5. A*算法实现猎人渡河问题
  6. position:absolute水平居中
  7. 解决safari浏览器打开页面会报错` Invalid Date`问题
  8. $.post()方法
  9. mysql分表的3种方法
  10. 外接键盘手感好?ROG GX501说并不需要