当前位置: 首页 > news >正文

ReentrantLock 源码解析与 AQS 扩展

一、ReentrantLock 概述

ReentrantLock是 Java 并发包中基于 AQS 实现的可重入锁,提供了比synchronized更灵活的锁控制功能,如可中断锁、公平锁、条件变量等。其核心设计特点:

  • 可重入性:同一线程可多次获取同一把锁而不会死锁

  • 公平 / 非公平可选:通过构造函数指定锁的公平策略

  • 条件变量支持:通过newCondition()创建多个条件变量

  • 手动锁管理:需显式调用lock()unlock()

二、ReentrantLock 的核心结构

2.1 继承关系与内部类

public class ReentrantLock implements Lock, java.io.Serializable {private final Sync sync;// 基础同步器,继承自AQSabstract static class Sync extends AbstractQueuedSynchronizer { ... }// 非公平锁实现static final class NonfairSync extends Sync { ... }// 公平锁实现static final class FairSync extends Sync { ... }// 构造函数public ReentrantLock() {sync = new NonfairSync(); // 默认非公平锁}public ReentrantLock(boolean fair) {sync = fair ? new FairSync() : new NonfairSync();}
}

2.2 对 AQS 的核心扩展点

ReentrantLock 通过重写 AQS 的以下关键方法实现锁功能:

AQS方法功能描述ReentrantLock实现方式
tryAcquire
尝试获取独占锁检查state状态并进行重入逻辑
tryRelease尝试释放独占锁递减state值 完全释放的时为 true
isHeldExclusively判断当前线程是否持有锁比较当前线程与锁的持有者

三、源码深度解析

3.1 非公平锁实现(NonfairSync)

3.1.1 锁获取流程

static final class NonfairSync extends Sync {final void lock() {// 第一步:直接尝试CAS获取锁if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());elseacquire(1); // 失败则走AQS标准流程}protected final boolean tryAcquire(int acquires) {return nonfairTryAcquire(acquires);}
}// 非公平锁的尝试获取逻辑
final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {// 锁未被持有,直接CAS竞争if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {// 重入逻辑:增加state值int nextc = c + acquires;if (nextc < 0) // overflowthrow new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;
}

3.1.2 锁释放流程

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); // 更新statereturn free;
}

3.2 公平锁实现(FairSync)

3.2.1 锁获取流程

static final class FairSync extends Sync {final void lock() {acquire(1); // 直接走AQS流程}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;}
}

3.2.2 公平性保证

hasQueuedPredecessors()方法是公平锁的核心:

 public final boolean hasQueuedPredecessors() {Thread first = null; Node h, s;if ((h = head) != null && ((s = h.next) == null ||(first = s.waiter) == null ||s.prev == null))first = getFirstQueuedThread(); // retry via getFirstQueuedThreadreturn first != null && first != Thread.currentThread();}

3.3 可中断锁与超时锁

3.3.1 可中断锁

中端锁是指线程在等待获取锁的过程中,能够响应外部中断信号(Thread.interrupt()),并收到中断信号后停止等待,退出阻塞状态的锁获取方式。

public void lockInterruptibly() throws InterruptedException {sync.acquireInterruptibly(1);
}// AQS中的实现
public final void acquireInterruptibly(int arg)throws InterruptedException {if (Thread.interrupted())throw InterruptedException();if (!tryAcquire(arg))doAcquireInterruptibly(arg); // 支持中断的等待逻辑
}private void doAcquireInterruptibly(int arg)throws InterruptedException {final Node node = addWaiter(Node.EXCLUSIVE);  // 创建独占模式节点并加入队列boolean failed = true;try {for (;;) {final Node p = node.predecessor();  // 获取前驱节点if (p == head && tryAcquire(arg)) {  // 前驱是头节点且能获取锁setHead(node);  // 当前节点设为头节点p.next = null;  // 帮助GCfailed = false;return;}// 检查是否需要阻塞if (shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt())  // 阻塞当前线程并检查中断状态throw new InterruptedException();  // 被中断则抛异常}} finally {if (failed)cancelAcquire(node);  // 取消获取锁操作}
}

3.3.2 超时锁

超时锁是指 线程在获取锁时,可设置一个最大等待时间,若在该时间内未成功获取锁,则自动放弃等待,返回 “获取失败”*的锁获取方式。其核心特点在于基于“时间触发”自动放弃等待,不需要外部信号干预。

public boolean tryLock(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}// AQS中的实现
public final boolean tryAcquireNanos(int arg, long nanosTimeout)throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();return tryAcquire(arg) ||doAcquireNanos(arg, nanosTimeout); // 带超时的等待逻辑
}private boolean doAcquireNanos(int arg, long nanosTimeout)throws InterruptedException {if (nanosTimeout <= 0L)  // 超时时间已过return false;final long deadline = System.nanoTime() + nanosTimeout;  // 计算截止时间final Node node = addWaiter(Node.EXCLUSIVE);  // 创建节点加入队列boolean failed = true;try {for (;;) {final Node p = node.predecessor();  // 获取前驱节点if (p == head && tryAcquire(arg)) {  // 前驱是头节点且能获取锁setHead(node);  // 当前节点设为头节点p.next = null;  // 帮助GCfailed = false;return true;}// 计算剩余超时时间nanosTimeout = deadline - System.nanoTime();if (nanosTimeout <= 0L) {  // 超时时间已过cancelAcquire(node);  // 取消获取锁return false;}// 检查是否需要阻塞以及剩余时间是否足够if (shouldParkAfterFailedAcquire(p, node) &&nanosTimeout > spinForTimeoutThreshold)  // 剩余时间足够则阻塞LockSupport.parkNanos(this, nanosTimeout);  // 限时阻塞if (Thread.interrupted())  // 检查中断状态throw new InterruptedException();}} finally {if (failed)cancelAcquire(node);  // 取消获取锁操作}
}

 3.4 条件变量实现

3.4.1 条件变量创建

public Condition newCondition() {return sync.newCondition();
}// Sync类中的实现
final ConditionObject newCondition() {return new ConditionObject();
}

3.4.2 等待与唤醒

// ConditionObject中的await()方法
public final void await() throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();Node node = addConditionWaiter(); // 添加到条件队列int savedState = fullyRelease(node); // 释放锁int interruptMode = 0;while (!isOnSyncQueue(node)) {LockSupport.park(this); // 阻塞线程if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)break;}// 唤醒后重新竞争锁if (acquireQueued(node, savedState) && interruptMode != THROW_IE)interruptMode = REINTERRUPT;if (node.nextWaiter != null) // clean up if cancelledunlinkCancelledWaiters();if (interruptMode != 0)reportInterruptAfterWait(interruptMode);
}// ConditionObject中的signal()方法
public final void signal() {if (!isHeldExclusively())throw new IllegalMonitorStateException();Node first = firstWaiter;if (first != null)doSignal(first); // 转移到AQS队列
}

四、ReentrantLock 对 AQS 的扩展总结

4.1 核心扩展点

扩展点实现方式与意义
可重入性通过 state 计数实现同一线程多次获取锁,释放时需递减至 0
公平策略公平锁通过hasQueuedPredecessors()检查队列顺序,非公平锁直接 CAS 竞争
可中断获取重写acquireInterruptibly()方法,在等待过程中响应中断
超时机制实现tryAcquireNanos()方法,支持带超时的锁获取
条件变量通过ConditionObject实现独立条件队列,支持更精细的线程协作

4.2 与 synchronized 的对比

特性ReentrantLocksynchronized
锁获取方式手动调用 lock () 和 unlock ()自动获取和释放
公平性可选择公平 / 非公平非公平
可中断性支持不支持
超时锁支持不支持
多条件变量支持单一 wait/notify 机制
性能高竞争场景更优低竞争场景更简单

http://www.dtcms.com/a/276391.html

相关文章:

  • 首次让机器人具备类人的「主动感知」能力
  • 淘宝商品评论API接口操作详解
  • oc分类和swift扩展有哪些区别
  • 火山引擎:字节跳动的技术赋能初解
  • AI智能体 | 使用Coze制作一键生成单词洗脑循环视频,一天批量生成100条视频不是梦!(附保姆级教程)
  • NW728NW733美光固态闪存NW745NW746
  • HashMap的原理
  • 技术面试问题总结二
  • 多模态大模型》多模态基础模型》多模态对齐、融合和表示
  • 关于数字签名
  • xml映射文件的方式操作mybatis
  • 集合类
  • 【2024CSP-J初赛】阅读程序(1)试题详解
  • python-while循环
  • Raft-领导者选举
  • import 和require的区别
  • python-range函数
  • jxWebUI--数据表
  • Anthropic:从OpenAI分支到AI领域的领军者
  • 连接池深度解析:原理、实现与最佳实践
  • 第六章 公司分析——基础
  • Kubernetes Volume存储卷概念
  • 骁龙8 Gen4前瞻:台积3nm工艺如何平衡性能与发热
  • 信号量核心机制说明及实际应用(结合ArduPilot代码)
  • C++类模版2
  • 人工智能大语言模型提供了一种打败小朋友十万个为什么的捷径
  • 附件1.2025年世界职业院校技能大赛赛道简介
  • 1. JVM介绍和运行流程
  • 计算机毕业设计springboot的零食推荐系统 基于SpringBoot的在线零食商城个性化推荐平台 JavaWeb驱动的智能零食选购与推荐系统
  • HT8313功放入门