Java并發(fā)編程之ReentrantLock的實現(xiàn)示例
一、可中斷鎖
1. 核心方法:lockInterruptibly()
- 作用:允許線程在等待鎖的過程中響應中斷請求。
- 適用場景:需要支持任務取消或中斷的同步操作(如用戶手動取消長時間等待的任務)。
2. 代碼示例
ReentrantLock lock = new ReentrantLock();
Thread thread = new Thread(() -> {
try {
lock.lockInterruptibly(); // 可中斷獲取鎖
try {
System.out.println("線程獲取鎖并執(zhí)行任務");
Thread.sleep(5000); // 模擬耗時操作
} finally {
lock.unlock();
}
} catch (InterruptedException e) {
System.out.println("線程被中斷,放棄獲取鎖");
}
});
lock.lock(); // 主線程先獲取鎖
try {
thread.start();
Thread.sleep(1000); // 確保子線程開始等待鎖
thread.interrupt(); // 中斷子線程
} finally {
lock.unlock();
}
3. 行為分析
- 未中斷時:線程正常獲取鎖并執(zhí)行任務。
- 中斷時:拋出
InterruptedException,線程退出等待隊列。
二、鎖超時
1. 核心方法:tryLock()
無參方法:
boolean tryLock()
立即嘗試獲取鎖,成功返回true,失敗返回false。帶超時方法:
boolean tryLock(long timeout, TimeUnit unit)
在指定時間內(nèi)嘗試獲取鎖,超時后放棄。
2. 代碼示例:避免死鎖
ReentrantLock lockA = new ReentrantLock();
ReentrantLock lockB = new ReentrantLock();
Thread thread1 = new Thread(() -> {
try {
if (lockA.tryLock(1, TimeUnit.SECONDS)) { // 嘗試獲取lockA
try {
if (lockB.tryLock(1, TimeUnit.SECONDS)) { // 嘗試獲取lockB
System.out.println("Thread1完成任務");
}
} finally {
if (lockB.isHeldByCurrentThread()) lockB.unlock();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (lockA.isHeldByCurrentThread()) lockA.unlock();
}
});
Thread thread2 = new Thread(() -> { /* 類似邏輯,先嘗試lockB再lockA */ });
thread1.start();
thread2.start();
3. 應用場景
- 死鎖預防:通過超時放棄鎖請求,打破循環(huán)等待。
- 響應性優(yōu)化:避免線程長時間阻塞影響系統(tǒng)響應速度。
三、條件變量
1. 核心機制
- 創(chuàng)建條件變量:
Condition condition = lock.newCondition(); - 等待條件:
condition.await(); - 喚醒線程:
condition.signal()或condition.signalAll()
2. 代碼示例:生產(chǎn)者-消費者模型
ReentrantLock lock = new ReentrantLock();
Condition notEmpty = lock.newCondition(); // 非空條件
Condition notFull = lock.newCondition(); // 非滿條件
Queue<Integer> queue = new LinkedList<>();
int maxSize = 10;
// 生產(chǎn)者
new Thread(() -> {
lock.lock();
try {
while (queue.size() == maxSize) {
notFull.await(); // 等待隊列非滿
}
queue.add(1);
notEmpty.signal(); // 通知消費者
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}).start();
// 消費者
new Thread(() -> {
lock.lock();
try {
while (queue.isEmpty()) {
notEmpty.await(); // 等待隊列非空
}
queue.poll();
notFull.signal(); // 通知生產(chǎn)者
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}).start();
3. 優(yōu)勢對比wait()/notify()
| 特性 | Condition | wait()/notify() |
|---|---|---|
| 多條件支持 | ? 可創(chuàng)建多個條件變量 | ? 每個對象僅一個等待隊列 |
| 精準喚醒 | ? signal() 喚醒指定條件隊列的線程 | ? notify() 隨機喚醒 |
四、關(guān)鍵注意事項
1. 鎖釋放
- 必須手動釋放:lock.unlock() 需放在 finally 塊中確保執(zhí)行。
- 重入次數(shù)匹配:加鎖和解鎖次數(shù)必須一致,否則導致鎖無法釋放。
2. 中斷處理
- 響應中斷:lockInterruptibly() 和 await() 需捕獲 InterruptedException。
- 恢復中斷狀態(tài):調(diào)用 Thread.currentThread().interrupt() 保留中斷標志。
到此這篇關(guān)于Java并發(fā)編程之ReentrantLock的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)Java ReentrantLock內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Data JPA 之 JpaRepository的使用
這篇文章主要介紹了Spring Data JPA 之 JpaRepository的使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02
使用Java和PostgreSQL存儲向量數(shù)據(jù)的實現(xiàn)指南
在當今的數(shù)字化時代,數(shù)據(jù)存儲的方式和技術(shù)正變得越來越復雜和多樣化,隨著機器學習和數(shù)據(jù)科學的發(fā)展,向量數(shù)據(jù)的存儲和管理變得尤為重要,本文將詳細介紹如何使用 Java 和 PostgreSQL 數(shù)據(jù)庫來存儲向量數(shù)據(jù),需要的朋友可以參考下2024-09-09
Java如何自定義類數(shù)組的創(chuàng)建和初始化
這篇文章主要介紹了Java如何自定義類數(shù)組的創(chuàng)建和初始化,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10
MyBatis 關(guān)聯(lián)查詢延遲加載實戰(zhàn)案例
本文介紹了MyBatis開發(fā)中一對多、一對一關(guān)聯(lián)查詢的配置方法,重點講解了resultMap、association、collection等核心標簽的使用場景和用語法,并詳細解釋了延遲加載(fetchType屬性)的配置方法和執(zhí)行流程,最后總結(jié)了單表查詢、一對一關(guān)聯(lián)和一對多關(guān)聯(lián)的配置方法和注意事項2026-05-05
Java如何把數(shù)組轉(zhuǎn)換為ArrayList
這篇文章主要介紹了Java如何把數(shù)組轉(zhuǎn)換為ArrayList,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-01-01
JVM入門之JVM內(nèi)存結(jié)構(gòu)內(nèi)容詳解
這篇文章主要介紹了JVM入門之JVM內(nèi)存結(jié)構(gòu)內(nèi)容詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-09-09

