ReentrantLock和RLock
文章目录
- 前言
- 一、 ReentrantLock(单机锁,Java 内置)
- 示例:
- 方法详解
- 二、RLock(分布式锁,Redisson 提供)
- 示例:
- 方法详解
- 三、 对比总结:
- 四、 如何选择?
前言
ReentrantLock 和 RLock 都是可重入锁(Reentrant Lock),但它们属于不同的锁实现,分别适用于 单机环境 和 分布式环境。
一、 ReentrantLock(单机锁,Java 内置)
ReentrantLock 是 Java 标准库(java.util.concurrent.locks)提供的可重入互斥锁,适用于 单机多线程 场景。特点可重入性:同一个线程可以多次获取同一把锁(避免死锁)。公平/非公平锁:支持公平锁(按等待顺序获取)和非公平锁(默认,允许插队)。可中断:lockInterruptibly() 允许线程在等待锁时响应中断。条件变量:支持 Condition,用于线程间协调(如 await() / signal())。必须手动释放:必须调用 unlock(),否则可能导致死锁。
示例:
ReentrantLock lock = new ReentrantLock();
try {if (lock.tryLock(1, TimeUnit.SECONDS)) { // 尝试获取锁,最多等1秒try {System.out.println("Lock acquired!");} finally {lock.unlock(); // 必须手动释放}}
} catch (InterruptedException e) {Thread.currentThread().interrupt();
}
方法详解
方法 | 说明 |
---|---|
lock() | 阻塞获取锁,如果锁被占用,当前线程会一直等待。 |
lockInterruptibly() | 可中断地获取锁,等待过程中可响应 InterruptedException。 |
tryLock() | 尝试非阻塞获取锁,成功返回 true,失败返回 false。 |
tryLock(long timeout, TimeUnit unit) | 在指定时间内尝试获取锁,超时返回 false。 |
unlock() | 释放锁(必须在 finally 块中调用,避免死锁)。 |
isLocked() | 判断锁是否被占用(非标准方法,需自定义实现)。 |
isHeldByCurrentThread() | 判断当前线程是否持有锁。 |
getHoldCount() | 返回当前线程持有锁的次数(可重入计数)。 |
getQueueLength() | 返回等待获取锁的线程数(监控用)。 |
hasQueuedThreads() | 是否有线程在等待锁。 |
newCondition() | 返回 Condition 对象,用于线程间协调(类似 wait/notify)。 |
二、RLock(分布式锁,Redisson 提供)
RLock 是 Redisson(Redis 客户端)提供的 分布式可重入锁,适用于 多机多进程 环境,基于 Redis 实现。特点可重入性:同 ReentrantLock,支持同一个客户端多次加锁。自动释放(Lease Time):可以设置锁的自动过期时间(防止死锁)。看门狗机制(Watchdog):如果未指定 leaseTime,Redisson 会启动一个后台线程(看门狗)自动续期锁,避免业务未执行完锁就过期。支持高可用:如果 Redis 是集群模式,RLock 仍然可用(Redisson 有 RedLock 算法)。支持异步锁:提供 lockAsync() 等异步方法。
示例:
RLock lock = redisson.getLock("myLock");
try {// 尝试获取锁,最多等10秒,锁自动30秒后释放if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {try {System.out.println("Lock acquired!");// 业务逻辑...} finally {lock.unlock(); // 建议手动释放(即使设置了leaseTime)}}
} catch (InterruptedException e) {Thread.currentThread().interrupt();
}
方法详解
方法 | 说明 |
---|---|
lock() | 阻塞获取锁,默认 看门狗自动续期(防止死锁)。 |
lock(long leaseTime, TimeUnit unit) | 获取锁并设置自动释放时间(leaseTime 后自动释放)。 |
lockInterruptibly() | 可中断获取锁(支持线程中断)。 |
tryLock() | 尝试获取锁,成功返回 true,失败返回 false。 |
tryLock(long waitTime, long leaseTime, TimeUnit unit) | 在 waitTime 内尝试获取锁,成功后锁在 leaseTime 后自动释放。 |
unlock() | 释放锁(建议在 finally 中调用)。 |
forceUnlock() | 强制释放锁(即使当前线程未持有)。 |
isLocked() | 判断锁是否被占用。 |
isHeldByCurrentThread() | 当前线程是否持有锁。 |
remainTimeToLive() | 返回锁的剩余存活时间(TTL)。 |
三、 对比总结:
四、 如何选择?
单机应用 ➝ ReentrantLock(更轻量,无网络开销)。
分布式系统 ➝ RLock(基于 Redis,适用于多服务竞争锁)。
需要自动释放 ➝ RLock(设置 leaseTime 防止死锁)。
需要条件变量 ➝ ReentrantLock(Condition 更灵活)。
如果你的应用是 微服务/分布式架构,RLock 是更好的选择;如果是 单机高并发,ReentrantLock 更高效。