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

深入解析ReentrantLock:可重入锁

目录

一、核心特性:为何需要ReentrantLock?

1. 可重入性

2. 作为synchronized的补充与增强

二、核心用法:API与最佳实践

三、公平锁 vs. 非公平锁

四、底层实现:AQS

五、synchronized和ReentrantLock的区别


在Java并发编程中,synchronized 是内置的关键字,而 ReentrantLock 则是 java.util.concurrent.locks 包提供的一个显式锁实现。它不仅是 synchronized 的强大替代品,更以其灵活性、可扩展性和丰富的功能,为开发者提供了更细粒度的并发控制手段。

一、核心特性:为何需要ReentrantLock?

1. 可重入性

与 synchronized 一样,ReentrantLock 也是可重入的。这意味着同一个线程可以多次获取同一把锁而不会产生死锁。锁内部维护了一个计数器(hold count)来跟踪锁被重复获取的次数,线程每次获取锁时计数器加1,每次释放锁时计数器减1,只有当计数器归零时,锁才被真正释放,其他线程才能获取。

2. 作为synchronized的补充与增强

虽然 synchronized 在大多数情况下已足够优秀且简洁,但 ReentrantLock 在以下方面提供了更高级的功能:

    • 尝试非阻塞地获取锁tryLock() 方法允许线程尝试获取锁,如果锁不可用则立即返回false,而不会像 synchronized 那样一直阻塞。

    • 可中断的锁获取lockInterruptibly() 方法允许在等待锁的过程中响应中断。

    • 超时获取锁tryLock(long time, TimeUnit unit) 方法可以指定超时时间,在指定时间内获取不到锁则返回false。

    • 公平性选择:构造函数允许选择创建一个公平锁(Fair Lock) 或非公平锁(Nonfair Lock)

二、核心用法:API与最佳实践

ReentrantLock 的使用遵循一个明确的模式,必须显式地加锁和解锁。

Lock lock = new ReentrantLock(); // 通常为非公平锁
// Lock lock = new ReentrantLock(true); // 创建一个公平锁lock.lock(); // 手动获取锁
try {// 临界区代码:执行需要同步的操作
} finally {lock.unlock(); // 必须在finally块中手动释放锁,确保锁必然被释放,避免死锁
}

重要必须将 unlock() 操作放在 finally 块中,以保证即使在临界区代码抛出异常的情况下,锁也能被正确释放。

三、公平锁 vs. 非公平锁

这是 ReentrantLock 提供的一个关键特性,synchronized 只提供非公平锁。

  • 非公平锁(默认):当锁可用时,所有正在等待的线程都有机会抢占,与等待时间无关。这可能导致“线程饥饿”(某些线程长时间得不到锁),但吞吐量更高,因为减少了线程切换的开销。

  • 公平锁:当锁可用时,它会优先分配给等待时间最长的线程。这保证了公平性,消除了饥饿,但性能开销较大,因为需要维护一个有序队列,吞吐量通常低于非公平锁。

选择策略:除非有严格的公平性要求,否则默认使用非公平锁,因为其性能优势在大多数场景下更为重要。

四、底层实现:AQS

ReentrantLock 的强大功能并非凭空实现,其核心是依赖一个叫做 AQS(AbstractQueuedSynchronizer) 的同步器框架。

AQS内部维护了一个 volatile int state(同步状态)和一个 FIFO线程等待队列(CLH变体)

  • 对于 ReentrantLockstate 表示锁被重入的次数。为0时表示锁空闲,大于0时表示被线程持有。

  • lock() 操作本质上是通过CAS去修改 state 的值。如果成功(从0改为1),则获取锁。

  • 如果失败,当前线程会被封装成Node节点,加入到等待队列中并可能被挂起。

  • unlock() 操作会将 state 减1。如果减为0,则唤醒等待队列中的下一个线程来尝试获取锁。

公平与非公平的实现差异就体现在 tryAcquire 方法中:公平锁在尝试获取锁前,会先检查等待队列中是否有其他线程在排队;而非公平锁则会直接尝试CAS抢占。

五、synchronized和ReentrantLock的区别

特性

synchronized

ReentrantLock

锁获取和锁释放

●隐式获取(由 JVM 自动处理,线程抢占模型)
●自动释放(代码块 / 方法执行完毕或异常退出)

显式调用 lock () 和 unlock ()方法手动控制(必须在 finally 块中调用 unlock(),否则可能导致死锁)

可中断性

不可中断

通过lockInterruptibly()方法,允许线程在等待锁时被中断

超时机制

不支持

通过 tryLock (timeout)方法,允许线程在指定时间内尝试获取锁

公平性

非公平

可选择公平或非公平

条件变量

单一 wait/notify

支持多个 Condition 对象

锁状态检测

无法判断

可通过方法检测锁状态(是否被当前线程持有、是否被其他线程持有)

锁实现机制

Monitor监视器

AQS同步框架


文章转载自:

http://lvZSa2B7.yrccw.cn
http://vUBUhfXj.yrccw.cn
http://PZZ69geK.yrccw.cn
http://wYEKAj8F.yrccw.cn
http://K0BlWtMP.yrccw.cn
http://KZPOD2Wp.yrccw.cn
http://lelJwQvD.yrccw.cn
http://Q4M6sFuR.yrccw.cn
http://BGAsBZf4.yrccw.cn
http://ax3Y433g.yrccw.cn
http://3lHuWJu0.yrccw.cn
http://gEmWKgxI.yrccw.cn
http://T4U6FEtQ.yrccw.cn
http://ja2BGg8W.yrccw.cn
http://dXNGLxJc.yrccw.cn
http://9wITMwyx.yrccw.cn
http://5rJNKXBw.yrccw.cn
http://ct2Y3xGr.yrccw.cn
http://OSLzBTom.yrccw.cn
http://Igny8sHI.yrccw.cn
http://fLg3o9kJ.yrccw.cn
http://zDEHaGfg.yrccw.cn
http://O0P5hrbI.yrccw.cn
http://1J4JtAwZ.yrccw.cn
http://0rS4Eo7I.yrccw.cn
http://p7reAPMN.yrccw.cn
http://7k2XQdMN.yrccw.cn
http://hF5xTBJk.yrccw.cn
http://hQ9x4EVM.yrccw.cn
http://zXA34km5.yrccw.cn
http://www.dtcms.com/a/377374.html

相关文章:

  • ARM处理器总线架构解析:iCode、D-code与S-Bus
  • Qoder 前端UI/UE升级改造实践:从传统界面到现代化体验的华丽蜕变
  • Flutter多线程
  • 如何在高通跃龙QCS6490 Arm架构上使用Windows 11 IoT企业版?
  • JavaScript 对象说明
  • CMake目标依赖关系解析
  • 小型企业常用的元数据管理工具
  • 论文AI写作哪个软件好?实测对比5款热门AI写作工具
  • PostgreSQL 内机器学习的关键智能算法研究
  • 12公里无人机图传模组:从模糊到超高清的飞跃,抗干扰能力全面升级
  • GitHub Actions中steps下面的Setup environment设置的环境变量不能在后面步骤使用问题处理
  • YOLOv5实战-GPU版本的pytorch虚拟环境配置
  • 苍穹外卖项目实战(day7-2)-购物车操作功能完善-记录实战教程、问题的解决方法以及完整代码
  • 【VsCode】离线状态下安装插件
  • 浏览器开发CEFSharp (十七)网页自定义下载—仙盟创梦IDE
  • Nodejs读取目录下面的文件
  • docker 重命名镜像
  • 「CTF」青少年CTF·雏形系统
  • 光子计算芯片实战:Lightmatter Passage互连架构性能评测
  • 实时多模态电力交易决策系统:设计与实现
  • 条码控件Aspose.BarCode教程:使用 C# 构建 Code11 条形码生成器
  • 分布式专题——7 Redis Stack扩展功能
  • QuestionPicture:一键批量改图,支持压缩图片
  • Prompt提示词(保姆级教程)
  • SSM病房管理信息系统o45h4(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • SpreadJS:让多源数据筛选排序如 Excel 般便捷高效
  • ARM内存映射与启动地址重映射机制解析
  • 如何使用 QuickAPI 快速连接 MySQL 数据库并发布 RESTful API
  • PAT 1104 Sum of Number Segments
  • LeetCode 热题 3.无重复字符的最长子串