ReentrantLock的实现原理

ReentrantLock 是 Java 中的一个高级同步机制,它提供了比传统的 synchronized 方法和语句更灵活的锁定操作。ReentrantLock 实现了 Lock 接口,并且完全依赖于 AbstractQueuedSynchronizer (AQS) 的扩展来实现其同步行为。

ReentrantLock 特性

  • 可重入: 同一个线程可以多次获得同一把锁。
  • 公平性: 可以设置锁的公平性。公平锁意味着等待时间最长的线程会首先获得锁。
  • 锁绑定多个条件: 可以绑定多个 Condition 实例,实现线程间更精细的同步。

ReentrantLock 实现原理

ReentrantLock 在内部通过其静态内部类 Sync 来使用 AQS。Sync 是一个抽象类,它扩展了 AQS,并提供了所有锁操作的基础。Sync 有两个子类 FairSyncNonfairSync,分别提供公平和非公平锁的操作。公平和非公平锁的主要区别在于是否考虑线程等待的顺序。

以下是 ReentrantLock 中的一些关键方法的内部实现概念:

lock()

非公平锁 (NonfairSync) 和公平锁 (FairSync) 的 lock() 方法略有不同。在非公平锁中,调用 lock() 会直接尝试获取锁,如果成功则立即返回,如果失败则进入同步队列等待。对于公平锁,当一个线程调用 lock(),它会首先检查是否有其他线程正等待获取锁,即使当前锁是可用的,也会保证按照等待的先后顺序来获取锁。

public void lock() {sync.lock();
}
unlock()

释放锁的操作是通过调用 AQS 的 tryRelease(int arg) 方法来实现的。tryRelease(int arg) 将会在成功释放锁时返回 true,通知后继节点的线程尝试获取锁。

public void unlock() {sync.release(1);
}
tryLock()

该方法尝试获取锁,如果锁立即可用(即不存在争用),则成功获取并返回 true;如果锁不可用,则返回 false,此方法不会等待。

public boolean tryLock() {return sync.nonfairTryAcquire(1);
}
lockInterruptibly()

该方法与 lock() 相似,但它允许在等待锁的过程中响应中断。如果当前线程在进入同步队列或者已经在队列中等待时被中断,它会抛出 InterruptedException 并退出锁申请。

public void lockInterruptibly() throws InterruptedException {sync.acquireInterruptibly(1);
}
newCondition()

ReentrantLock 提供了自己的 Condition 实现,这允许与内部锁状态进行更紧密的协作。

public Condition newCondition() {return sync.newCondition();
}

AQS 在 ReentrantLock 中的使用

ReentrantLock 在 AQS 的基础上定义了资源(锁)的获取和释放方式:

  • 获取锁: AQS 通过 tryAcquire(int arg) 方法的覆写来定义锁的获取行为。如果当前状态为0,说明锁未被持有,试图设置状态为1表示锁被当前线程独占。
  • 释放锁: AQS 通过 tryRelease(int arg) 方法的覆写来定义锁的释放行为。它尝试将状态设置回0,以便其他线程可以获取锁。

这些重写的方法会利用 AQS 提供的原子性状态操作方法,如 getState(), setState(int newState), compareAndSetState(int expect, int update) 等来管理同步状态。

ReentrantLock 的源码示例

下面是一个简化版的 ReentrantLock 实现,突出显示了 AQS 在其中的应用:

public class ReentrantLock implements Lock, java.io.Serializable {private final Sync sync;abstract static class Sync extends AbstractQueuedSynchronizer {abstract void lock();final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0) // overflowthrow new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}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);}setState(c);return free;}// 省略其他方法...}static final class NonfairSync extends Sync {final void lock() {if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());elseacquire(1);}// 省略其他方法...}static final class FairSync extends Sync {final void lock() {acquire(1);}// 省略其他方法...}// 构造函数 - 创建公平或非公平的锁public ReentrantLock(boolean fair) {sync = fair ? new FairSync() : new NonfairSync();}// 实现Lock接口的方法public void lock() {sync.lock();}// 省略其他方法...
}

在上述示例中,ReentrantLock 包含两个 Sync 的内部类,FairSyncNonfairSynclock() 方法调用 acquire(1),它是 AQS 中的方法,负责管理队列中线程的排队和阻塞行为。tryAcquire(int arg)tryRelease(int arg) 方法在 Sync 类中被定义,它们通过 AQS 提供的方法来操作同步状态。

通过这种方式,ReentrantLock 利用 AQS 的基础设施来实现锁的功能,并提供了丰富的同步操作。

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

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

相关文章

【数字孪生】Nginx发布数字孪生三维建模模型服务及调用方法

【数字孪生】Nginx发布数字孪生三维建模模型服务及调用方法 一、需求二、实施步骤2.1 准备模型文件2.1.1 3D tiles模型2.1.2 3D Tiles标准文件格式 2.2 配置nginx server块2.2.1 Nginx能干啥 2.3 访问 三、实现效果 一、需求 利用三维渲染引擎Cesium加载3D tiles模型。 二、实…

(学习日记)2024.03.16:UCOSIII第十八节:任务的删除

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

下载JDK17版本详细教程(下载、安装、环境变量配置)

官网下载 Oracle 甲骨文中国 | 云应用和云平台 安装 更改自己的安装位置。点击下一步&#xff0c;记住自己的安装位置 环境配置 右键此电脑点击属性---高级系统设置----环境变量 在系统变量里面点击新建环境变量JAVA_HOME&#xff0c;下面填入自己的jdk安装地址&#xff0c…

关于微服务跨数据库联合查询的一些解决思路

微服务架构的一个非常明显的特征就是一个服务所拥有的数据只能通过这个服务的API来访问。通过这种方式来解耦&#xff0c;这样就会带来查询问题。以前通过join就可以满足要求&#xff0c;现在如果需要跨多个服务集成查询就会非常麻烦。 解决思路 下面提供几个思路仅供参考 表…

【鸿蒙HarmonyOS开发笔记】常用组件介绍篇 —— Toggle切换按钮组件

概述 Toggle为切换按钮组件&#xff0c;一般用于两种状态之间的切换&#xff0c;例如下图中的蓝牙开关。 参数 Toggle组件的参数定义如下 Toggle(options: { type: ToggleType, isOn?: boolean })● type type属性用于设置Toggle组件的类型&#xff0c;可通过ToggleType枚举…

python异常:pythonIOError异常python打开文件异常

1.python读取不存在的文件时&#xff0c;抛出异常 通过 open()方法以读“r”的方式打开一个 abc.txt 的文件&#xff08;该文件不存在&#xff09;&#xff0c;执行 open()打开一个不存在的文件时会抛 IOError 异常&#xff0c;通过 Python 所提供的 try...except...语句来接收…

linux查看服务器登录成功和登录失败的命令

last 查看成功登录服务器的信息&#xff0c;包括ip&#xff0c;时间&#xff0c;登录用户&#xff0c;时长。lastb 查看登录服务器失败的信息。 last命令实例&#xff1a; 其他参数&#xff1a; -a&#xff1a;把从何处登入系统的主机名称或ip地址&#xff0c;显示在最后一行…

.rmallox勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复

导言&#xff1a; 近年来&#xff0c;勒索病毒的威胁日益增加&#xff0c;其中一种名为.rmallox的勒索病毒备受关注。这种病毒通过加密文件并勒索赎金来威胁受害者。本文将介绍.rmallox勒索病毒的特点&#xff0c;以及如何恢复被其加密的数据文件&#xff0c;并提供预防措施&a…

Css提高——flex布局及其相关属性

目录&#xff1a; 1、传统布局与flex布局的区别 2、flex的布局原理 3、flex常见的父项属性 3.1、flex-direction &#xff1a;设置主轴的方向 3.2、justify-content 设置主轴上的子元素排列方式 3.3、flex-wrap 设置子元素是否换行 3.4、align-items 设置侧轴上的子元素排…

Linux:系统初始化,内核优化,性能优化(1)

我们安装好了一个服务器之后&#xff0c;一定要对他的系统&#xff0c;内核&#xff0c;性能一系列进行一个优化&#xff0c;否则当大并发的情况下很可能出现问题&#xff0c;我把要优化的东西直接罗列出来并介绍&#xff0c;后期可以直接编写一个脚本拿到服务器上直接用就行 …

在深圳,为什么硬件工程师的待遇还不如软件?

深圳触觉智能科技有限公司 硬件明明比软件更难&#xff0c;为何在国内… 硬件明明比软件更难&#xff0c;但硬件工程师待遇却不如软件工程师&#xff0c;硬件工程师常被忽视&#xff0c;被视为可轻易模仿的“配角”&#xff0c;默默付出却鲜获认可。比如八年以上的资深硬件工…

linux 内核升级-离线

离线升级 首先找到镜像网址&#xff1a;http://elrepo.org/tiki/Download 我选择了 https://mirrors.tuna.tsinghua.edu.cn/elrepo/kernel/el7/x86_64/RPMS/ 下载安装包 wget https://mirrors.tuna.tsinghua.edu.cn/elrepo/kernel/el7/x86_64/RPMS/elrepo-release-7.0-6.el7…

2024年普通人的创业机会在哪里?2024热门创业项目!2024普通人想翻身的风口行业!

创业千万别冲动&#xff0c;社区团购代理创业失败案例&#xff01; 是不是一开始挺看好这个赛道&#xff0c;看别人做的风生水起&#xff0c;以为不难&#xff0c;真正开始做才发现不好做&#xff0c;没有先天优势&#xff0c;货源和客源从零开始积累&#xff0c;开始就是摸着石…

Java 世界破破烂烂,电音小猫缝缝补补

Java 世界破破烂烂&#xff0c;电音小猫缝缝补补 Java 通用代码生成器光 2.4.0 电音之王尝鲜版六正在研发&#xff0c;昨天发布了介绍视频&#xff0c;请见&#xff1a; https://www.bilibili.com/video/BV1yD421j7UP/ 电音之王尝鲜版六支持哑数据模式&#xff0c;支持枚举。…

uniapp APP 上传文件

/*** 上传文件*/uploadPhoneFile:function(callback,params {}) {let fileType [.pdf,.doc,.xlsx,.docx,.xls]// #ifdef APP-PLUSplus.io.chooseFile({title: 选择文件, filetypes: [doc, docx], // 允许的文件类型 multiple: false, // 是否允许多选 },(e)>{const tem…

软件测试面试200问,面试看这就够了。。。

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 Part1 1、你的测试职业发展是什么&#xff1f; 测试经验越多&#xff0c;测试能力越高。所以我…

学嵌入式真的很烧钱吗?

如果是走嵌入式单片机方向&#xff0c;这篇内容&#xff0c;很适合预算1000以下的&#xff0c;作为发育参考。 下面是我2011年的入行成本&#xff1a; 买了智能小车&#xff0c;还有51开发板&#xff0c;杂七杂八&#xff0c;可能一共不到1000。 一开始迷之自信了&#xff0c;买…

软件测试方法 -- 等价类边界值

测试用例的定义 测试用例是为了特定的目的而设计的一组测试输入、执行条件和预期的结果&#xff0c;以便测试是否满足某个特定需求。通过大量的测试用例来检验软件的运行效果&#xff0c;他是指导测试工作进行的依据。 下面我们介绍几种常用的黑盒测试方法 等价类划分法 定…

数据表示—二进制与十进制转换

1. 二进制转十进制 按照数据类型分为三种&#xff1a;无符号的二进制整数&#xff0c;有符号的二进制整数和小数二进制数。 1.1 无符号的二进制整数 计算技巧&#xff1a; 从二进制数的右边第一位起&#xff0c;从右往左&#xff0c;先用二进制位置上的数乘以2的相应位数的幂&…