文章目錄
- 前言
- 一、 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 更高效。