概述

什么是 “可重入”,可重入就是说某个线程已经获得某个锁,可以再次获取锁而不会出现死锁。

可重入锁的意义之一在于防止死锁

package com.test.reen;// 演示可重入锁是什么意思,可重入,就是可以重复获取相同的锁,synchronized和ReentrantLock都是可重入的
// 可重入降低了编程复杂性
public class WhatReentrant {public static void main(String[] args) {new Thread(new Runnable() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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();}
}

可重入锁实现原理

每一个锁关联一个owner 线程持有者 和 state 计数器,当计数器为 0 时表示该锁没有被任何线程持有,那么任何线程都可能获得该锁而调用相应的方法;当某一线程请求成功后,JVM 会记下锁的持有线程,并且将计数器置为 1;此时其它线程请求该锁,则必须等待;而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增;当线程退出同步代码块时,计数器会递减,如果计数器为 0,则释放该锁。(源码层面分析)


附:原理分析

本文仅介绍如何使用,如需了解 ReentrantLock 原理(源码分析),请跳转了解:可重入锁 ReentrantLock 原理分析

End

可重入锁 ReentrantLock相关推荐

  1. 并发编程-19AQS同步组件之重入锁ReentrantLock、 读写锁ReentrantReadWriteLock、Condition

    文章目录 J.U.C脑图 ReentrantLock概述 ReentrantLock 常用方法 synchronized 和 ReentrantLock的比较 ReentrantLock示例 读写锁R ...

  2. Java 重入锁 ReentrantLock 原理分析

    1.简介 可重入锁ReentrantLock自 JDK 1.5 被引入,功能上与synchronized关键字类似.所谓的可重入是指,线程可对同一把锁进行重复加锁,而不会被阻塞住,这样可避免死锁的产生 ...

  3. java中的账户冻结原理_java可重入锁(ReentrantLock)的实现原理

    前言 相信学过java的人都知道 synchronized 这个关键词,也知道它用于控制多线程对并发资源的安全访问,兴许,你还用过Lock相关的功能,但你可能从来没有想过java中的锁底层的机制是怎么 ...

  4. java多线程---重入锁ReentrantLock

    1.定义 重入锁ReentrantLock,支持重入的锁,表示一个线程对资源的重复加锁. 2.底层实现 每个锁关联一个线程持有者和计数器,当计数器为0时表示该锁没有被任何线程持有,那么任何线程都可能获 ...

  5. 重入锁ReentrantLock详解

    重入锁ReentrantLock,顾名思义,就是支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁.除此之外,该锁的还支持获取锁时的公平和非公平性选择. 在AQS实现中,当一个线程调用Mute ...

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

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

  7. java lock可重入_Java源码解析之可重入锁ReentrantLock

    本文基于jdk1.8进行分析. ReentrantLock是一个可重入锁,在ConcurrentHashMap中使用了ReentrantLock. 首先看一下源码中对ReentrantLock的介绍. ...

  8. Java多线程——重入锁ReentrantLock源码阅读

    上一章<AQS源码阅读>讲了AQS框架,这次讲讲它的应用类(注意不是子类实现,待会细讲). ReentrantLock,顾名思义重入锁,但什么是重入,这个锁到底是怎样的,我们来看看类的注解 ...

  9. Java 并发编程之可重入锁 ReentrantLock

    Java 提供了另外一个可重入锁,ReentrantLock,位于 java.util.concurrent.locks 包下,可以替代 synchronized,并且提供了比 synchronize ...

  10. JDK1.8源码分析:可重入锁ReentrantLock和Condition的实现原理

    synchronized的用法和实现原理 synchronized实现线程同步的用法和实现原理 不足 synchronized在线程同步的使用方面,优点是使用简单,可以自动加锁和解锁,但是也存在一些不 ...

最新文章

  1. 详解 Vue Vuex 实践
  2. JPOM - AOP+自定义注解实现操作日志记录
  3. 3分钟了解dubbo服务调试管理实用命令
  4. Cannot find module -----Node.js编程的第一个问题
  5. “Survey of machine learning techniques for malware analysis ”
  6. SQL2000: MMC 不能打开文件
  7. html:(3):认识html标签和标签的语法
  8. 最全android Demo
  9. 鱼骨图分析法实际案例_会用“鱼骨图”的项目经理无难题
  10. zookeeper安装和使用
  11. 2019.08.29定时器以及轮播图
  12. 微服务的通信协议:Restful,RPC(Dubbo、Motan、gRPC)
  13. 【动态规划】leetcode 53:最大子数组和
  14. NLP学习—20.WMD paper及代码
  15. iOS 程序上传流程
  16. 参考文献中英文人名_英文人名的缩写和参考文献写法
  17. VS Visual Studio 2022调试控制台 输出不全 不完整 缺内容 少了很多代码 有屋设计拆单管理一体化软件 全屋定制拆单 橱柜衣柜整装 木门归方程序
  18. 小程序:npm下载使用weiui
  19. 传统企业互联网转型升级新玩法:技术合伙
  20. Spring AOP 标签形式及Around增强处理

热门文章

  1. Excel催化剂开源第6波-Clickonce部署之自动升级瘦身之术
  2. bert tensorflow2 serving部署
  3. java thrift使用指南_Thrift使用指南
  4. 魔众刮刮卡抽奖系统 v2.0.0 支付抽奖,更好用的刮刮卡系统
  5. 硬盘分区大学计算机,电脑硬盘容量要怎么选?又要怎么硬盘合理分区?今天我再说一次!...
  6. HomeKit 设备接入协议
  7. 《程序员的自我修养》学习笔记之温故而知新
  8. 记一次云主机如何挂载对象存储
  9. 四个Channel的讲解
  10. php执行fastlane,fastlane教程