ReentrantLock 用法与源码剖析笔记

news/2025/2/26 9:48:33

📒 ReentrantLock 用法与源码剖析笔记


🚀 一、ReentrantLock 核心特性
  • 🔄 可重入性:同一线程可重复获取锁(最大递归次数为 Integer.MAX_VALUE
  • 🔧 公平性:支持公平锁(按等待顺序获取)和非公平锁(默认,允许插队)
  • 超时机制tryLock(long timeout, TimeUnit unit)
  • 🚫 可中断lockInterruptibly() 允许响应中断
  • 🔗 条件变量Condition 实现精准线程唤醒(对比 Object.wait/notify

🛠️ 二、基础用法模板
java">ReentrantLock lock = new ReentrantLock();
// 非公平锁(默认) vs 公平锁(new ReentrantLock(true))

lock.lock();  // 📌 阻塞获取锁
try {
    // 临界区代码
} finally {
    lock.unlock();  // ⚠️ 必须放在 finally 块!
}

// 高级用法示例
if (lock.tryLock(1, TimeUnit.SECONDS)) {  // ⏳ 带超时尝试
    try {
        // ...
    } finally {
        lock.unlock();
    }
}

🔍 三、源码架构分析

image-20250225234605218

  1. Sync 同步器(继承 AQS)

    • NonfairSync(非公平锁实现)
    • FairSync(公平锁实现)
  2. AQS 核心机制

    • state 字段:锁状态计数器(0=未锁定,>0=锁定次数)
    • CLH 队列:线程等待队列(双向链表实现)

⚙️ 四、关键方法源码解析
🔑 1. lock() 方法对比
java">// 非公平锁实现
final void lock() {
    if (compareAndSetState(0, 1))  // 🚀 直接尝试插队
        setExclusiveOwnerThread(Thread.currentThread());
    else
        acquire(1);
}

// 公平锁实现
final void lock() {
    acquire(1);  // ⚖️ 必须排队
}

// AQS 核心方法
public final void acquire(int arg) {
    if (!tryAcquire(arg) && 
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}
🔄 2. tryAcquire 差异
java">// 非公平锁 tryAcquire
protected final boolean tryAcquire(int acquires) {
    return nonfairTryAcquire(acquires);  // 🎲 允许插队
}

// 公平锁 tryAcquire
protected final boolean tryAcquire(int acquires) {
    if (getQueueLength() > 0 && 
        getExclusiveOwnerThread() != Thread.currentThread()) {
        return false;  // 🚧 队列有等待线程时禁止获取
    }
    // ...后续与非公平锁相同
}

💡 五、设计亮点与注意事项
  • 性能取舍:非公平锁吞吐量更高(减少线程切换),但可能产生线程饥饿
  • 锁释放必须:unlock() 必须执行(建议用 try-finally 包裹)
  • 🧵 Condition 高级用法:实现多条件等待(典型应用:生产者-消费者模型)
  • ⚠️ 避免死锁:加锁顺序要一致,超时机制可作为兜底

📊 六、与 synchronized 对比
特性ReentrantLocksynchronized
实现机制API 层面JVM 内置
锁释放必须显式 unlock()自动释放
公平性可配置非公平
中断响应支持不支持
条件变量多 Condition单 Object monitor
性能高竞争时更优优化后差距缩小

🌟 七、最佳实践建议
  • 🆚 优先选择:需要高级功能时用 ReentrantLock,简单场景用 synchronized
  • 🧪 锁测试:用 ThreadMXBean 检测死锁
  • 📏 锁粒度:尽量缩小锁作用域
  • 🧮 性能监控:关注 getQueueLength() 等统计方法

http://www.niftyadmin.cn/n/5868501.html

相关文章

Linux之loop设备(Loop Devices in Linux)

Linux之loop设备 在Linux/Unix系统中,loop设备是一项非常实用的技术,它允许我们将普通文件作为块设备来使用。今天,让我们深入了解loop设备的工作原理及其应用场 一、Loop设备概述 Loop设备(loop device)是一种虚拟块设备,它能…

JS宏进阶:浅谈曲线回归

曲线回归是一种统计学方法,用于研究两个或多个变量之间的非线性关系,并找到最能拟合数据点的曲线函数形式。与线性回归不同,曲线回归适用于描述那些不是直线性的变量关系。通过曲线回归,可以建立变量之间的非线性数学模型,用于预测和解释各种实际现象。 一、基本概念 定…

EX_25/2/25

编写一个如下场景: 有一个英雄Hero类,私有成员,攻击,防御,速度,生命值,以及所有的set get 方法 编写一个 武器 Weapon 类,拥有私有成员攻击力,以及set get 方法 编写一个…

fps项目总结:网格体

文章目录 网格体碰撞物理:穿模时弹开 角色组件碰撞:角色网格体要触发命中则双方必须有一方开启物理模拟。组件开启物理将不再跟随根节点变换,且成为场景中的根节点。 网格体 碰撞 物理:穿模时弹开 角色组件 碰撞:角…

代码随想录第二十天|二叉树part08--669.修建二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树

刷题小记: 上期学习了二叉搜索树的插入和删除操作,这次学习如何按区间修剪二叉搜索树。还有两题,关于借助二叉搜索树的有序特性进行转换。 669.修剪二叉搜索树(669.修剪二叉搜索树) 题目分析: 给定一个…

Proof Beyond Boundaries: Hong Kong zkNight 活动精彩回顾

2 月 19 日,随着夜幕的降临,一场汇聚行业智慧与前瞻视野的高端主题活动 ——Proof Beyond Boundaries: Hong Kong zkNight,在香港铜锣湾 Vpoint 的 6/F 盛大启幕。本次活动由 ZEROBASE 主办,Techub News 承办,吸引了众…

mysql中的计算日期函数 理解、用法

三种计算日期的函数 函数用途示例DATEDIFF()计算两个日期的天数差DATEDIFF(2023-10-05, 2023-10-01) → 4TIMESTAMPDIFF()按指定单位(年、月、小时等)计算差TIMESTAMPDIFF(MONTH, 2023-01-01, 2023-03-01) → 2DATE_ADD()日期加法DATE_ADD(2023-10-01, …

数据安全_笔记系列05:数据合规与隐私保护(GDPR、CCPA、中国《数据安全法》)深度解析

数据安全_笔记系列05:数据合规与隐私保护(GDPR、CCPA、中国《数据安全法》)深度解析 在全球数据跨境流动和隐私保护强监管的背景下,企业需同时满足多法域合规要求。以下从 法规要点、核心差异、实施策略、跨境传输、典型案例 等维…