Java使用StampedLock實(shí)現(xiàn)高效讀寫(xiě)功能
使用 StampedLock實(shí)現(xiàn)高效讀寫(xiě)
1. 它是什么?
StampedLock 是 Java 8 引入的高性能鎖,提供了三種鎖模式:寫(xiě)鎖、悲觀讀鎖和樂(lè)觀讀鎖。
與傳統(tǒng)的 ReentrantReadWriteLock 相比,StampedLock 更注重性能,特別適合讀多寫(xiě)少的場(chǎng)景。
- 寫(xiě)鎖:阻塞所有其他操作(類(lèi)似獨(dú)占鎖)。
- 悲觀讀鎖:共享鎖,允許多個(gè)線程讀取,但會(huì)阻塞寫(xiě)操作。
- 樂(lè)觀讀鎖:一種非阻塞讀操作,允許并發(fā)寫(xiě)操作,并在必要時(shí)驗(yàn)證數(shù)據(jù)一致性。
2. 它的使用場(chǎng)景是什么?
- 讀多寫(xiě)少的場(chǎng)景:如緩存、配置數(shù)據(jù)讀取等場(chǎng)景,
StampedLock的樂(lè)觀讀鎖可以顯著提高性能。 - 需要快速讀鎖驗(yàn)證的場(chǎng)景:在樂(lè)觀讀的情況下,可以驗(yàn)證數(shù)據(jù)的一致性并在必要時(shí)降級(jí)為悲觀讀鎖。
- 寫(xiě)鎖需要優(yōu)先處理的場(chǎng)景:避免傳統(tǒng)讀寫(xiě)鎖中寫(xiě)線程因讀操作而長(zhǎng)期饑餓的問(wèn)題。
3. 它有哪些 API?
核心 API
| 方法名稱(chēng) | 描述 |
|---|---|
writeLock() | 獲取寫(xiě)鎖,返回一個(gè) stamp(鎖標(biāo)識(shí))。 |
readLock() | 獲取悲觀讀鎖,返回一個(gè) stamp(鎖標(biāo)識(shí))。 |
tryOptimisticRead() | 獲取樂(lè)觀讀鎖,返回一個(gè) stamp,非阻塞,適合快速讀取。 |
unlockWrite(long stamp) | 釋放寫(xiě)鎖,需要傳入獲取鎖時(shí)返回的 stamp。 |
unlockRead(long stamp) | 釋放悲觀讀鎖,需要傳入獲取鎖時(shí)返回的 stamp。 |
validate(long stamp) | 驗(yàn)證樂(lè)觀讀鎖期間是否有寫(xiě)操作發(fā)生,返回 true 表示數(shù)據(jù)未被修改。false表示數(shù)據(jù)已經(jīng)被修改過(guò) |
擴(kuò)展 API
| 方法名稱(chēng) | 描述 |
|---|---|
tryWriteLock() | 嘗試獲取寫(xiě)鎖,如果未成功立即返回。 |
tryReadLock() | 嘗試獲取讀鎖,如果未成功立即返回。 |
tryConvertToWriteLock(long stamp) | 嘗試將當(dāng)前鎖轉(zhuǎn)換為寫(xiě)鎖,成功時(shí)返回新 stamp,否則返回 0。 |
tryConvertToReadLock(long stamp) | 嘗試將當(dāng)前鎖轉(zhuǎn)換為讀鎖,成功時(shí)返回新 stamp,否則返回 0。 |
isWriteLocked() | 檢查當(dāng)前鎖是否有寫(xiě)鎖被占用。 |
isReadLocked() | 檢查當(dāng)前鎖是否有讀鎖被占用。 |
4. 它的使用方式
(1)寫(xiě)鎖的使用
public void updateValue(double deltaX, double deltaY) {
long stamp = lock.writeLock(); // 獲取寫(xiě)鎖
try {
x += deltaX;
y += deltaY;
} finally {
lock.unlockWrite(stamp); // 釋放寫(xiě)鎖
}
}
(2)悲觀讀鎖的使用
public double readValue() {
long stamp = lock.readLock(); // 獲取讀鎖
try {
return Math.sqrt(x * x + y * y);
} finally {
lock.unlockRead(stamp); // 釋放讀鎖
}
}
(3)樂(lè)觀讀鎖的使用
public double readValueOptimistically() {
long stamp = lock.tryOptimisticRead(); // 獲取樂(lè)觀讀鎖
double currentX = x, currentY = y;
if (!lock.validate(stamp)) { // 驗(yàn)證數(shù)據(jù)是否一致
stamp = lock.readLock(); // 如果不一致,降級(jí)為悲觀讀鎖
try {
currentX = x;
currentY = y;
} finally {
lock.unlockRead(stamp); // 釋放悲觀讀鎖
}
}
return Math.sqrt(currentX * currentX + currentY * currentY);
}
(4)鎖升級(jí)的使用
public void conditionalUpdate(double deltaX, double deltaY) {
long stamp = lock.readLock(); // 獲取悲觀讀鎖
try {
if (x == 0 && y == 0) { // 檢查條件
stamp = lock.tryConvertToWriteLock(stamp); // 升級(jí)為寫(xiě)鎖
if (stamp == 0L) { // 如果升級(jí)失敗
stamp = lock.writeLock(); // 顯式獲取寫(xiě)鎖
}
x += deltaX;
y += deltaY;
}
} finally {
lock.unlock(stamp); // 釋放鎖
}
}
5. 它有哪些注意事項(xiàng)
(1)StampedLock 不可重入 StampedLock 不支持重入。如果同一線程嘗試再次獲取鎖(無(wú)論讀鎖還是寫(xiě)鎖),會(huì)導(dǎo)致死鎖。
(2)鎖釋放需要傳入正確的 stamp 每次加鎖時(shí)都會(huì)返回一個(gè)唯一的 stamp,在釋放鎖時(shí)需要傳入對(duì)應(yīng)的 stamp,否則會(huì)拋出 IllegalMonitorStateException。
(3)寫(xiě)優(yōu)先策略 StampedLock 優(yōu)先滿足寫(xiě)鎖請(qǐng)求,避免了讀寫(xiě)鎖可能出現(xiàn)的寫(xiě)線程饑餓問(wèn)題。
(4)線程安全 StampedLock 是線程安全的,但不支持條件變量(Condition),因此無(wú)法直接使用 wait 或 notify。
(5)適用場(chǎng)景 適合 讀多寫(xiě)少 的場(chǎng)景。 不適合寫(xiě)頻繁的場(chǎng)景,因?yàn)閷?xiě)鎖的爭(zhēng)用會(huì)導(dǎo)致性能下降。
總結(jié)
StampedLock 是 Java 并發(fā)工具庫(kù)中的一顆“冷門(mén)寶石”,它通過(guò)樂(lè)觀讀鎖提供了高效的非阻塞讀機(jī)制,同時(shí)避免了寫(xiě)線程饑餓的問(wèn)題。熟悉其 API 和使用場(chǎng)景,能夠幫助你在性能敏感的場(chǎng)景中實(shí)現(xiàn)更高效的并發(fā)控制!
以上就是Java使用StampedLock實(shí)現(xiàn)高效讀寫(xiě)功能的詳細(xì)內(nèi)容,更多關(guān)于Java StampedLock高效讀寫(xiě)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java web SpringMVC后端傳json數(shù)據(jù)到前端頁(yè)面實(shí)例代碼
本篇文章主要介紹了java web SpringMVC后端傳json數(shù)據(jù)到前端頁(yè)面實(shí)例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-03-03
SpringBoot中驗(yàn)證用戶上傳的圖片資源的方法
這篇文章主要介紹了在SpringBoot中驗(yàn)證用戶上傳的圖片資源,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09
maven私有鏡像倉(cāng)庫(kù)nexus部署使用
Nexus在企業(yè)開(kāi)發(fā)中還是比較常用的私有倉(cāng)庫(kù)管理工具,本文主要介紹了maven私有鏡像倉(cāng)庫(kù)nexus部署使用,具有一定的參考價(jià)值,感興趣的可以了解一下2024-07-07
Java?任務(wù)調(diào)度框架?Quartz實(shí)操
這篇文章主要介紹了Java?任務(wù)調(diào)度框架?Quartz,Quartz是OpenSymphony開(kāi)源組織在Job?scheduling領(lǐng)域又一個(gè)開(kāi)源項(xiàng)目,完全由Java開(kāi)發(fā),可以用來(lái)執(zhí)行定時(shí)任務(wù),類(lèi)似于java.util.Timer。,下面我們來(lái)學(xué)習(xí)一下關(guān)于?Quartz更多的詳細(xì)內(nèi)容,需要的朋友可以參考一下2021-12-12
SpringMvc配置靜態(tài)資源訪問(wèn)路徑的實(shí)現(xiàn)
本文主要介紹了SpringMvc配置靜態(tài)資源訪問(wèn)路徑的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
Spring Data JPA 整合QueryDSL的使用案例
QueryDSL 是一個(gè)用于構(gòu)建類(lèi)型安全的 SQL 查詢(xún)的 Java 庫(kù),它的主要目標(biāo)是簡(jiǎn)化在 Java 中構(gòu)建和執(zhí)行 SQL 查詢(xún)的過(guò)程,同時(shí)提供類(lèi)型安全性和更好的編碼體驗(yàn),對(duì)Spring Data JPA 整合QueryDSL使用案例感興趣的朋友跟隨小編一起看看吧2023-08-08
spring boot tomcat版本升級(jí)的實(shí)現(xiàn)示例
本文主要介紹了spring boot tomcat版本升級(jí)的實(shí)現(xiàn)示例,將tomcat升級(jí)一個(gè)小版本升級(jí)到9.0.44版本,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-11-11
Java?面向?qū)ο笸ㄟ^(guò)new揭開(kāi)對(duì)象實(shí)例化
各位鐵汁們大家好呀,我們上次博客講了,通過(guò)?Student?student1?=?new?Student();就可以實(shí)例化一個(gè)對(duì)象,這個(gè)對(duì)象就有Student類(lèi)中的所以成員變量。可是?對(duì)象student1?和?類(lèi)Student到底是怎樣建立聯(lián)系的,在內(nèi)存中到底發(fā)生了什么2022-04-04

