JAVA并发十:ReentrantLock

Java并发之ReentrantLock原理详解 一、ReentrantLock是什么?    ReentrantLock是Lock接口的默认实现,是一种独占锁。相对synchronized而言,ReentrantLock提供了更多的操作方式以及更细粒度的加锁方式。    主要特性:    (1)可重入。ReentrantLock是可重入锁,因为它会记录之前获得锁线程对象,保存在exclusiveOwenerThread变量中,当一个线程要获取锁... 阅读详情
阅读精选内容,加入我们投稿,点这里!

作者:Java菜鸟奋斗史,本文为原创投稿文章

欢迎点击阅读原文,直达原作者文章围观。

知音专栏

 

 程序员的出路

 关于资源视频下载的说明

【强化编程功底】算法文摘


1. ReentrantLock的介绍

ReentrantLock重入锁,是实现Lock接口的一个类,也是在实际编程中使用频率很高的一个锁,支持重入性,表示能够对共享资源能够重复加锁,即当前线程获取该锁再次获取不会被阻塞。


在java关键字synchronized隐式支持重入性(关于synchronized可以看这篇文章),synchronized通过获取自增,释放自减的方式实现重入。与此同时,ReentrantLock还支持公平锁和非公平锁两种方式。


那么,要想完完全全的弄懂ReentrantLock的话,主要也就是ReentrantLock同步语义的学习:重入性的实现原理; 公平锁和非公平锁。


2. 重入性的实现原理

要想支持重入性,就要解决两个问题:


在线程获取锁的时候,如果已经获取锁的线程是当前线程的话则直接再次获取成功; 由于锁会被获取n次,那么只有锁在被释放同样的n次之后,该锁才算是完全释放成功。


通过这篇文章,我们知道,同步组件主要是通过重写AQS的几个protected方法来表达自己的同步语义。针对第一个问题,我们来看看ReentrantLock是怎样实现的,以非公平锁为例,判断当前线程能否获得锁为例,核心方法为nonfairTryAcquire:

final boolean nonfairTryAcquire(int acquires) {
   final Thread current = Thread.currentThread();
   int c = getState();
   //1. 如果该锁未被任何线程占有,该锁能被当前线程获取
 if (c == 0) {
       if (compareAndSetState(0, acquires)) {
           setExclusiveOwnerThread(current);
           return true;
       }
   }
 //2.若被占有,检查占有线程是否是当前线程
   else if (current == getExclusiveOwnerThread()) {
   // 3. 再次获取,计数加一
       int nextc = c + acquires;
       if (nextc < 0) // overflow
           throw new Error("Maximum lock count exceeded");
       setState(nextc);
       return true;
   }
   return false;
}


这段代码的逻辑也很简单,具体请看注释。为了支持重入性,在第二步增加了处理逻辑,如果该锁已经被线程所占有了,会继续检查占有线程是否为当前线程,如果是的话,同步状态加1返回true,表示可以再次获取成功。


每次重新获取都会对同步状态进行加一的操作,那么释放的时候处理思路是怎样的了?(依然还是以非公平锁为例)核心方法为tryRelease:

protected final boolean tryRelease(int releases) {
 //1. 同步状态减1
   int c = getState() - releases;
   if (Thread.currentThread() != getExclusiveOwnerThread())
       throw new IllegalMonitorStateException();
   boolean free = false;
   if (c == 0) {
   //2. 只有当同步状态为0时,锁成功被释放,返回true
       free = true;
       setExclusiveOwnerThread();
   }
 // 3. 锁未被完全释放,返回false
   setState(c);
   return free;
}


代码的逻辑请看注释,需要注意的是,重入锁的释放必须得等到同步状态为0时锁才算成功释放,否则锁仍未释放。如果锁被获取n次,释放了n-1次,该锁未完全释放返回false,只有被释放n次才算成功释放,返回true。


到现在我们可以理清ReentrantLock重入性的实现了,也就是理解了同步语义的第一条。


3. 公平锁与公平锁

ReentrantLock支持两种锁:公平锁和非公平锁。何谓公平性,是针对获取锁而言的,如果一个锁是公平的,那么锁的获取顺序就应该符合请求上的绝对时间顺序,满足FIFO。ReentrantLock的构造方法无参时是构造非公平锁,源码为:

public ReentrantLock() {
   sync = new NonfairSync();
}


另外还提供了另外一种方式,可传入一个boolean值,true时为公平锁,false时为非公平锁,源码为:

public ReentrantLock(boolean fair) {
   sync = fair ? new FairSync() : new NonfairSync();
}


在上面非公平锁获取时(nonfairTryAcquire方法)只是简单的获取了一下当前状态做了一些逻辑处理,并没有考虑到当前同步队列中线程等待的情况。我们来看看公平锁的处理逻辑是怎样的,核心方法为:

protected final boolean tryAcquire(int acquires) {
   final Thread current = Thread.currentThread();
   int c = getState();
   if (c == 0) {
       if (!hasQueuedPredecessors() &&
           compareAndSetState(0, acquires)) {
           setExclusiveOwnerThread(current);
           return true;
       }
   }
   else if (current == getExclusiveOwnerThread()) {
       int nextc = c + acquires;
       if (nextc < 0)
           throw new Error("Maximum lock count exceeded");
       setState(nextc);
       return true;
   }
   return false;
 }
}


这段代码的逻辑与nonfairTryAcquire基本上一直,唯一的不同在于增加了hasQueuedPredecessors的逻辑判断,方法名就可知道该方法用来判断当前节点在同步队列中是否有前驱节点的判断,如果有前驱节点说明有线程比当前线程更早的请求资源,根据公平性,当前线程请求资源失败。


如果当前节点没有前驱节点的话,再才有做后面的逻辑判断的必要性。公平锁每次都是从同步队列中的第一个节点获取到锁,而非公平性锁则不一定,有可能刚释放锁的线程能再次获取到锁。


公平锁  VS  非公平锁


公平锁每次获取到锁为同步队列中的第一个节点,保证请求资源时间上的绝对顺序,而非公平锁有可能刚释放锁的线程下次继续获取该锁,则有可能导致其他线程永远无法获取到锁,造成“饥饿”现象。


公平锁为了保证时间上的绝对顺序,需要频繁的上下文切换,而非公平锁会降低一定的上下文切换,降低性能开销。因此,ReentrantLock默认选择的是非公平锁,则是为了减少一部分上下文切换,保证了系统更大的吞吐量。


【Java知音】实时干货推荐栏

Java并发专题【10】彻底理解ReentrantLock

Java并发编程(十) : JUC 之 AQS介绍、AQS核心思想、自定义不可重入阻塞锁、ReentrantLock原理、Condition介绍及原理 J.U.C 8.2.1 AQS 原理 概述:全称是 AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架 特点: 用 state 属性来表示资源的状态(分独占模式和共享模式),子类需要定义如何维护这个状态,控制如何获取锁和释放锁 getState - 获取 state 状态 setState - 设置 state 状态 compareAndSetState - cas 机制设置 state 状态 独占模式是只有一个线程能够访问资源,而共享模式可以允许多个线程访问资源 阅读详情

相关推荐

深入解析PCIe Retimer:工作原理与典型应用场景

本文深入解析了PCIe Retimer的工作原理与核心价值。作为高速信号的中继再生器,Retimer通过时钟数据恢复和信号再生技术,有效解决长距离或复杂通道中的信号衰减与完整性问题,从而极大地扩展了PCIe链路的有效传输距离。文章详细阐述了其内部架构、自动与手动两种工作模式,并重点介绍了在长距离板间互连、复杂背板设计等典型应用场景中的关键作用。

weixin_29195615的博客 506

Java 重入锁 ReentrantLock使用实战

1.简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”。 其可以完全替代 synchronized 关键字。JDK 1.5.0 引入的,其性能远好于 synchronized,但 JDK 1.6.0 开始,JDK 对 synchronized 做了大量的优化,使得两者差距并不大。但其提供了超出synchonized的其他高级功能(例如,中断锁等候、条件变量等),并且...

程序员小强的博客 7481

STM32 SYSTICK定时器及延时函数详解

STM32 SYSTICK及延时函数详解 SysTick定时器 SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。例如,为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心

w1050321758的博客 2366

Java锁详解之ReentrantLock

ReentrantLock是除了synchronized用得较多的一种锁。ReentrantLock也属于重入锁,后面接着就会提到它的重入锁实现原理。 ReentrantLock的功能要比内部锁synchronized更多,如指定锁等待时间的方法tryLock(long time,TimeUnit unit)、中断锁的方法lockInterruptibly()、没获取锁直接返回的方法tryLock...

爱雨轩 3125

逆向实战:拼多多anti-content加密参数的全链路解析与动态对抗策略

本文深入解析了拼多多anti-content加密参数的全链路生成逻辑与动态对抗策略。通过逆向工程实战,详细拆解了包含设备指纹、用户行为采集和动态密钥生成在内的12个关键环节,并提供了可持续对抗的精准模拟方案和自动化更新机制,帮助开发者有效应对拼多多的反爬体系。

weixin_30687051的博客 160

基于FastLIO2与TEB算法的机器狗自主导航系统实战

本文详细介绍了如何为机器狗构建一套基于FastLIO2与TEB算法的自主导航系统。通过整合FastLIO2激光惯性里程计实现精准定位,并采用TEB局部规划器进行灵活路径规划与动态避障,解决了传统方案在复杂地形下反应慢、易碰撞的问题。文章提供了从环境搭建、算法部署、地图转换到系统调试的完整实战指南,帮助开发者实现机器狗的稳健自主行走。

beer8的博客 320

java中的ReentrantLock

随时随地阅读更多技术实战干货,获取项目源码、学习资料,请关注源代码社区公众号(ydmsq666) 一、概述 结构: java.lang.Object java.util.concurrent.locks.ReentrantLock 声明:public class ReentrantLock ex...

孤云博客 4921

Gazebo仿真平台模型搭建与修改

ROS里踩过的坑(一)Gazebo仿真平台模型搭建与修改文件讲解Models 文件World文件Launch文件模型编辑可视化编辑配置文件编辑模型展示如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出...

Redglass的博客 1万+

java锁原理图_轻松学习java可重入锁(ReentrantLock)的实现原理(转 图解)

前言相信学过java的人都知道 synchronized 这个关键词,也知道它用于控制多线程对并发资源的安全访问,兴许,你还用过Lock相关的功能,但你可能从来没有想过java中的锁底层的机制是怎么实现的。如果真是这样,而且你有兴趣了解,今天我将带领你轻松的学习下java中非常重要,也非常基础的可重入锁-ReentrantLock的实现机制。听故事把知识掌握了在一个村子里面,有一口井水,水质非常的...

weixin_39628180的博客 301

Android16 自定义HAL层适配一些VINTF和SELINUX问题修改

在RK里面一般权限矩阵在/rockchip/common/manifests/目录,我这版Android16的代码比较特殊,这里重点修改/device/rockchip/rockchip_generic/manifests/frameworks_compatibility_matrix.xml这个文件,不同的版本注册方式不同,在。hal_ruip_default.te,hal_ruip.te,attributes文件。拓展策略的方式添加,但是在Android16里面发现用不了。发现HAL层服务注册成功了。

tzj1058756809的博客 242

SolidWorks速成教程P4-4【装配体 | 第四节】——装配体内修改模型&编辑配合方法&配合报错的解决方法

截止目前已介绍完 SolidWorks装配体的常用功能,但基础薄弱的小伙伴或许对装配体的各类功能还不够熟悉。所以这节将进一步加强装配体的学习,同时介绍新手容易犯的错误。总结出三点,一是装配体内修改模型,二是编辑配合,三是配合报错的解决方法。

嵌入式阿齐Archie 5552

PKI体系简易JAVA实现(一):时间戳服务器TSA

1.时间戳服务器TSA的概念: 作为一个权威的、可信赖的、公正的第三方数字证书颁发机构,其时间戳服务就是将经过时间戳服务器签名的一个可信赖的日期和时间与特定电子数据绑定在一起,为服务器端和客户端应用提供可信的时间证明。   2.网上能看到的泛滥的时间戳工作示意图: 我之前找到的资料里都有这个图。这个图从概念上讲述了时间戳服务的流程。但是如果我们要从代码上模拟一个TSA出来,这个图并没有...

NNever的专栏 2213

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

reentrantlock java,JAVA并发十:彻底理解ReentrantLock

作者:Java菜鸟奋斗史,本文为原创投稿文章欢迎点击阅读原文,直达原作者文章围观。1. ReentrantLock的介绍ReentrantLock重入锁,是实现Lock接口的一个类,也是在实际编程中使用频率很高的一个锁,支持重入性,表示能够对共享资源能够重复加锁,即当前线程获取该锁再次获取不会被阻塞。在java关键字synchronized隐式支持重入性(关于synchronized可以看这篇文章...

weixin_42231085的博客 121

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

JAVA并发十:彻底理解ReentrantLock

原博地址:https://www.javazhiyin.com/6265.html 1. ReentrantLock的介绍 ReentrantLock重入锁,是实现Lock接口的一个类,也是在实际编程中使用频率很高的一个锁,支持重入性,表示能够对共享资源能够重复加锁,即当前线程获取该锁再次获取不会被阻塞。 在java关键字synchronized隐式支持重入性,synchronized通过获取自增,释放自减的方式实现重入。与此同时,ReentrantLock还支持公平锁和非公平锁两种方式。 那么,要想完完全

今天的BUG保熟。 138

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Java并发编程(十):ReentrantLock-NonfairSync源码逐行深度分析(中)

,同样在AQS中找到该方法的实现: final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { //标识是否被中断 boolean interrupted = false; //死循环 for (;;) { //获取node节点的前驱节点

黄智霖的博客 6516

Java并发之ReentrantLock详解

一、入题        ReentrantLock是Java并发包中互斥锁,它有公平锁和非公平锁两种实现方式,以lock()为例,其使用方式为: ReentrantLock takeLock = new ReentrantLock(); // 获取锁 takeLock.lock(); try { // 业务逻辑 } finally {

辰辰爸的博客 2万+

【Java并发】【ReentrantLock】适合初学体质的ReentrantLock入门

马上跟上主播的节奏,看看怎么使用ReentrantLock,这个比较简单,非常适合我们新人朋友奥!本文只介绍简单的使用,具体原理,主播下一篇具体研究🤗是 Java 并发包 () 中的一个类,它实现了Lock接口,提供了与关键字类似的互斥锁功能,但具有更高的灵活性和扩展性。主要特点可重入性与一样,是可重入的。这意味着同一个线程可以多次获取同一个锁,而不会导致死锁。每次获取锁后,必须相应地进行相同次数的释放。公平性支持公平锁和非公平锁。

flzjkl的博客 1091

Java ReentrantLock 高并发机制解析

在当今的软件开发领域,高并发编程已成为一项至关重要的技能。特别是在处理多线程应用时,如何有效地管理线程同步和互斥成为了一个核心问题。Java作为一门广泛应用于企业级应用开发的语言,提供了多种机制来支持高并发编程。其中,ReentrantLock是Java并发编程库中的一个重要组成部分,它提供了一种比synchronized关键字更为灵活和强大的锁机制。想象一个在线银行系统,该系统需要处理大量的并发交易请求。在这个系统中,为了保证数据的一致性和完整性,多个线程可能需要同时访问同一份数据。

AIHacksCash的博客 1032

彻底理解Java并发:ReentrantLock锁

本篇内容包括:为什么使用 Lock、Lock 锁注意事项、ReentrantLock 和 synchronized 对比、ReentrantLock (加锁、解锁、公平锁与非公平锁、ReentrantLock 如何实现可重入)等内容。

栗筝i的博客 6033

Java 并发编程详解:Lock 接口及其实现 ReentrantLock

Lock接口 提供了比 synchronized 关键字更灵活和丰富的锁机制。是 Lock 接口的一个实现,支持可重入、可选择的公平锁以及提供 Condition 对象来实现复杂的线程间协调。使用 ReentrantLock 可以提高多线程环境下程序的并发性能和可控性,适用于需要复杂锁控制的场景。通过合理使用 Lock 接口及其实现 ReentrantLock,可以更有效地管理并发,确保线程安全,提高程序的可靠性和性能。

微笑听雨 6026

基于ReentrantLock的Java并发编程探索

并发编程是指在计算机系统中,同时执行多个独立的任务或操作的一种编程方式。在现代计算机系统中,利用多核处理器、分布式系统等技术,实现并发性已经成为常态。提高系统性能:通过并发编程,可以充分利用计算资源,同时执行多个任务,提高系统的吞吐量和响应速度。例如,可以将一个大型任务拆分成多个子任务并行执行,加快整体处理速度。提升用户体验:对于需要实时响应的应用程序,如网络服务器、图形界面程序等,采用并发编程可以避免因单线程阻塞而导致的界面卡顿或响应延迟,提升用户体验。资源利用率提高。

q1372302825的博客 1251

面试 Java 并发编程八股文十问十答第七期

面试必备八股文!内容包含:Java基础、Java框架、Git命令、JVM、多线程、消息队列、微服务、Linux、数据库、Redis缓存、算法、Vue、React、前端性能优化等八股文。

qq_67358181的博客 1013

java的reentrantlock_Java并发之ReentrantLock详解

一、入题ReentrantLock是Java并发包中互斥锁,它有公平锁和非公平锁两种实现方式,以lock()为例,其使用方式为:ReentrantLock takeLock = new ReentrantLock();// 获取锁takeLock.lock();try {// 业务逻辑} finally {// 释放锁takeLock.unlock();}那么,ReentrantLock内部是如何...

weixin_35406812的博客 1837

Java并发编程 - ReentrantLock

本文主要介绍了Java并发包下的ReentrantLock并发工具类的概念和基本使用,文章内容涵盖了ReentrantLock的语法、特性、条件变量等知识点,并结合经典案例-哲学家就餐问题来演示了ReentrantLock解决死锁的能力,同时展示了ReentrantLock的一个经典设计模式案例-交替输出字符串。

ikun的博客 974

Java并发:ReentrantLock原理、应用与优秀实践

对了,各位看官,小生才情有限,笔墨之间难免会有不尽如人意之处,还望多多包涵,不吝赐教。感激不尽,咱们一起加油哦!公平锁遵循先来先服务的原则,而非公平锁则允许插队,即新来的线程有机会抢占正在等待的线程的锁。例如,在缓存系统中,大部分时间都是读取数据,偶尔才会有更新操作,这时使用读写锁可以显著提高系统的性能。你可以把这里当作自己的家,无论是工作之余的小憩,还是寻找灵感的驿站,我都希望你能在这里找到属于你的那份快乐和满足。

master_chenchen的博客 1303
上一篇: JAVA并发九:深入理解AbstractQueuedSynchronizer(AQS)
下一篇: JAVA并发十一:深入理解读写锁ReentrantReadWriteLock
SATTSA
博客等级 码龄8年 9粉丝 13原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值