ReentrantLock底层原理、源码解析

        ReentrantLock 的底层原理涉及到 Java 线程调度、锁的实现机制以及 AQS(AbstractQueuedSynchronizer)框架。

1. AQS 框架

ReentrantLock 是基于 AQS 实现的。AQS 是一个用于构建锁和其他同步组件的基础框架,它使用了一个 FIFO 队列来管理线程的等待顺序。

  • State 变量:AQS 使用一个 volatile int state 变量来记录锁的状态。对于 ReentrantLock 来说,这个变量表示当前锁被持有的次数。

  • CLH 队列:AQS 内部维护了一个 CLH(Craig, Landin, and Hagersten)队列,这是一个双向队列,用于管理等待获取锁的线程。

2. 锁的获取与释放

获取锁 (lock())

  • 非公平模式

    • 线程首先尝试通过 CAS(Compare And Swap)操作直接获取锁(即修改 state 变量)。如果成功,则继续执行。

    • 如果失败,检查当前线程是否已经持有锁(可重入性),如果是,则增加 state 计数。

    • 如果仍然失败,将线程加入 CLH 队列并阻塞。

  • 公平模式

    • 线程会先检查队列中是否有其他线程在等待,如果有,则直接进入队列等待,不会尝试直接获取锁。

    • 如果没有其他线程在等待,则尝试通过 CAS 操作获取锁。

释放锁 (unlock())

  • 当线程调用 unlock() 方法时,会减少 state 计数。

  • 如果 state 计数变为 0,表示锁完全释放,唤醒队列中的下一个线程。

  • 如果 state 计数不为 0,说明当前线程仍然是锁的持有者,可以继续执行。

3. 可重入性

  • ReentrantLock 支持可重入特性,即同一个线程可以多次获取同一把锁而不会发生死锁。

  • 每次获取锁时,state 计数器加1;每次释放锁时,计数器减1;当计数器为0时,表示锁完全释放。

4. 条件变量

  • ReentrantLock 还支持条件变量(Condition),允许线程在某个条件下等待或唤醒其他线程。

  • 条件变量内部也是基于 AQS 实现的,使用了 AQS 的 ConditionObject 类。

源码(解析在注释中):

import java.util.concurrent.TimeUnit;
import java.util.Collection;public class ReentrantLock implements Lock, java.io.Serializable {private static final long serialVersionUID = 7373984872572414699L;private final Sync sync;// 继承AQSabstract static class Sync extends AbstractQueuedSynchronizer {private static final long serialVersionUID = -5179523762034025860L;abstract void lock();/*** 不公平尝试获取锁* @param acquires* @return*/final boolean nonfairTryAcquire(int acquires) {// 获取当前线程final Thread current = Thread.currentThread();int c = getState();if (c == 0) {if (compareAndSetState(0, acquires)) { // 如果当前无线程持有锁,进行cas尝试上锁setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) { // 如果该线程本来就持有锁,state增加,表示锁的重入int nextc = c + acquires;if (nextc < 0)throw new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}/*** state 减 release * @param releases* @return*/protected final boolean tryRelease(int releases) {int c = getState() - releases;if (Thread.currentThread() != getExclusiveOwnerThread())throw new IllegalMonitorStateException();boolean free = false;if (c == 0) { // 释放完全 持有线程设置为空free = true;setExclusiveOwnerThread(null);}// 设置state 为 减去 releases后的值setState(c);return free;}/*** 判断持有锁线程是否为当前线程**/protected final boolean isHeldExclusively() {return getExclusiveOwnerThread() == Thread.currentThread();}/*** *  获取当前持有持有锁的线程,无则返回null*/final Thread getOwner() {return getState() == 0 ? null : getExclusiveOwnerThread();}/*** 获取state(重入数量),只有持有锁的线程可以获取*/final int getHoldCount() {return isHeldExclusively() ? getState() : 0;}/*** 判断是否有线程上锁*/final boolean isLocked() {return getState() != 0;}}/*** 非公平锁*/static final class NonfairSync extends Sync {private static final long serialVersionUID = 7316153563782823691L;/***  当前线程cas与aqs等待队列头的线程竞争, cas竞争失败会进入等待队列*/final void lock() {if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());elseacquire(1);}// 尝试获取锁,或者重入protected final boolean tryAcquire(int acquires) {return nonfairTryAcquire(acquires);}}/*** 公平锁*/static final class FairSync extends Sync {private static final long serialVersionUID = -3000897897090466540L;/***  直接放入等待队列,排队上锁*/final void lock() {acquire(1);}/***  尝试获取锁,或者重入*/protected final boolean tryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) { // 如果当前线程无需排队(前面没有在等待的线程)且 cas获取锁成功,设置持有线程为当前线程if (!hasQueuedPredecessors() &&compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) { // 重入 state + acquiresint nextc = c + acquires;if (nextc < 0)throw new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}}// 构造方法,默认不公平public ReentrantLock() {sync = new NonfairSync();}// 指定是否公平public ReentrantLock(boolean fair) {sync = fair ? new FairSync() : new NonfairSync();}// 后面就不再一一解释了,都是sync的方法。
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/495001.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Selenium 和 Playwright两大框架的不同之处

自动化测试工具百花齐放&#xff0c;其中 Selenium 和 Playwright 是两大热门框架&#xff0c;谁才是你的最佳选择&#xff1f;面对企业项目的真实需求&#xff0c;它们的差异究竟在哪儿&#xff1f; Selenium 和 Playwright 是两种流行的自动化测试工具&#xff0c;它们都被用…

智能化军事【五】精确制导武器智能化实现

文章目录 前言精确制导武器智能化实现基于深度学习实现的智能化功能基于强化学习实现的智能化功能强化学习深度强化学习 网络模型轻量化网络剪枝&#xff08;通道剪枝&#xff09;技术层剪枝权值量化技术低秩近似技术知识蒸馏技术强化学习联合训练 解决有效训练样本不足或获取困…

Windows内核开发环境配置

SDK 软件开发工具包 r3用到的win32api 就是SDK WDK 驱动内核 r0用到的包 Previous WDK versions and other downloads - Windows drivers | Microsoft Learn sdk版本必须和wdk版本一致 驱动环境部署 #include <ntifs.h>NTSTATUS DriverUnload(PDRIVER_OBJECT pDriver) …

图像处理-Ch6-彩色图像处理

Ch6 彩色图像处理 无广告更易阅读&#xff0c;个人博客点此进入<– 文章目录 Ch6 彩色图像处理彩色基础彩色模型(Color models)RGB(red, green, blue)CMY & CMYK(cyan, magenta, yellow/and black)HSI(hue, saturation, intensity)HSV(hue, saturation, value) 颜色空…

window安装TradingView

目录 下载安装包 修改文件后缀&#xff0c;解压 将K线换成国内涨红跌绿样式 下载安装包 https://www.tradingview.com/desktop/ 下载完成后是.msix格式文件 &#xff08;我在win10和win11的系统中尝试运行msix都没有成功&#xff0c;所以放弃直接双击运行msix&#xff…

畅捷通T+13管理员密码任意重置漏洞

复现版本 畅捷通13 漏洞复现 POST /tplus/ajaxpro/RecoverPassword,App_Web_recoverpassword.aspx.cdcab7d2.ashx?methodSetNewPwd HTTP/1.1 Host: 192.168.1.8:8080 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0 Accept…

搭建Elastic search群集

一、实验环境 二、实验步骤 Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎Elasticsearch目录文件&#xff1a; /etc/elasticsearch/elasticsearch.yml#配置文件 /etc/elasticsearch/jvm.options#java虚拟机 /etc/init.d/elasticsearch#服务启动脚本 /e…

三.统一异常Exception拦截处理

文章目录 前言一、先定义一个业务异常类二、定义全局异常处理器二、测试小插曲抛出异常&#xff1a;抛出自定义异常&#xff1a; 总结 前言 上一章对统一返回值进行封装&#xff0c;但是都是基于正常情况下的返回&#xff0c;系统难免会出现异常的情况&#xff0c;我们不可能在…

Xcode 16 编译弹窗问题、编译通过无法,编译通过打包等问题汇总

问题1&#xff1a;打包的过程中不断提示 &#xff1a;codesign 想要访问你的钥匙串中的密钥“develop 或者distribution 证书” 解决&#xff1a;打开钥匙串&#xff0c;点击证书---显示简介---信任----改为始终信任 &#xff08;记住 &#xff1a;不能只修改钥匙的显示简介的…

汽车IVI中控开发入门及进阶(44):杰发科智能座舱芯片

概述: 杰发科技自成立以来,一直专注于汽车电子芯片及相关系统的研发与设计。 产品布局: 合作伙伴: 杰发科技不断提升产品设计能力和产品工艺,确保产品达 到更高的质量标准。目前杰发科技已通过ISO9001质 量管理体系与CMMIL3认证。 杰发科技长期合作的供应商(芯片代工厂、…

Linux系统安装部署xtrabackup

简介 xtrabackup一款强大的在线热备份工具备份过程中不锁库表&#xff0c;适合生产环境由专业组织Percona提供&#xff08;改进MySQL分支&#xff09; 下载xtrabackup xtrabackup官网地址&#xff1a;https://www.percona.com/ 进去官网后&#xff0c;下滑到底部导航栏&…

有没有检测吸烟的软件 ai视频检测分析厂区抽烟报警#Python

在现代厂区管理中&#xff0c;安全与规范是重中之重&#xff0c;而吸烟行为的管控则是其中关键一环。传统的禁烟管理方式往往依赖人工巡逻&#xff0c;效率低且存在监管死角&#xff0c;难以满足当下复杂多变的厂区环境需求。此时&#xff0c;AI视频检测技术应运而生&#xff0…

idea设置控制台日志输出自动换行

文章目录 1. 原因2. 方法一&#xff1a;3. 方法二&#xff1a; 1. 原因 你是否碰到ideal控制台输入日志是一行的效果&#xff0c;那是因为带了soft wrap。 2. 方法一&#xff1a; 最新版的IDEA设置控制台自动换行位置如下&#xff1a; Setting->Editor->General->C…

某科技局国产服务器PVE虚拟化技术文档

环境介绍 硬件配置 服务器品牌&#xff1a;黄河 型号&#xff1a;Huanghe 2280 V2 Cpu型号&#xff1a;kunpeng-920 磁盘信息 :480SSD * 2 ,4T*4 网卡&#xff1a;板载四口千兆 如下表 四台服务器同等型号配置&#xff0c;均做单节点虚拟化&#xff0c;数据保护采用底层r…

华为实训课笔记 2024 1223-1224

华为实训 12/2312/24 12/23 [Huawei]stp enable --开启STP display stp brief --查询STP MSTID Port Role STP State Protection 实例ID 端口 端口角色 端口状态 是否开启保护[Huawei]display stp vlan xxxx --查询制定vlan的生成树计算结…

个人笔记:ORM数据库框架EFCore使用示例,运行通过,附源码

个人笔记&#xff1a;ORM数据库框架EFCore使用示例&#xff0c;运行通过&#xff0c;附源码 0.新建项目1. 设置环境1.1. 添加 NuGet 包1.2. 创建模型类 2. 创建上下文类3. 创建数据库和表3.1. 启用迁移3.2. 更新数据库 4. 插入数据5. 查询数据6. 更新数据7. 删除数据8. 完整示例…

vue 集成 webrtc-streamer 播放视频流 - 解决阿里云内外网访问视频流问题

资料&#xff1a; 史上最详细的webrtc-streamer访问摄像机视频流教程-CSDN博客 webrtc目录 前端集成 html文件夹里的webrtcstreamer.js&#xff0c;集成到前端&#xff0c;可以访问webrtc&#xff0c;转换rtsp为webrtc视频流&#xff0c;在前端video中播放 <videoref&quo…

Unity3D仿星露谷物语开发5之角色单例模式

1、目的 使用单例模式创建角色对象&#xff0c;保证整个游戏中只有一个角色&#xff0c;并且让游戏对象具有全局可访问性。 2、流程 &#xff08;1&#xff09;创建SingletonMonobehaviour脚本 Assets下创建Scripts目录用于存放所有的脚本&#xff0c;再创建Misk子目录&…

DevNow x Notion

前言 Notion 应该是目前用户量比较大的一个在线笔记软件&#xff0c;它的文档系统也非常完善&#xff0c;支持多种文档格式&#xff0c;如 Markdown、富文本、表格、公式等。 早期我也用过一段时间&#xff0c;后来有点不习惯&#xff0c;就换到了 Obsidian &#xff0c;但是…

hCaptcha 图像识别 API 对接说明

hCaptcha 图像识别 API 对接说明 本文将介绍一种 hCaptcha 图像识别 API 对接说明&#xff0c;它可以通过用户输入识别的内容和 hCaptcha验证码图像&#xff0c;最后返回需要点击的小图像的坐标&#xff0c;完成验证。 接下来介绍下 hCaptcha 图像识别 API 的对接说明。 申请…