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)文章
SpringBoot+Spring?Data?JPA整合H2數(shù)據(jù)庫(kù)的示例代碼
H2數(shù)據(jù)庫(kù)是一個(gè)開(kāi)源的關(guān)系型數(shù)據(jù)庫(kù),本文重點(diǎn)給大家介紹SpringBoot+Spring?Data?JPA整合H2數(shù)據(jù)庫(kù)的示例代碼,感興趣的朋友跟隨小編一起看看吧2022-02-02
5個(gè)JAVA入門(mén)必看的經(jīng)典實(shí)例
這篇文章主要為大家詳細(xì)介紹了5個(gè)JAVA入門(mén)必看的經(jīng)典實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
Java實(shí)戰(zhàn)之實(shí)現(xiàn)用戶登錄
這篇文章主要介紹了Java實(shí)戰(zhàn)之實(shí)現(xiàn)用戶登錄,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-04-04
java實(shí)現(xiàn)浮點(diǎn)數(shù)轉(zhuǎn)人民幣的小例子
java實(shí)現(xiàn)浮點(diǎn)數(shù)轉(zhuǎn)人民幣的小例子,需要的朋友可以參考一下2013-03-03
SpringBoot項(xiàng)目動(dòng)態(tài)指定配置文件的方法示例
SpringBoot 作為 Java 開(kāi)發(fā)中一個(gè)非常流行的框架,以其簡(jiǎn)化配置和快速啟動(dòng)應(yīng)用而聞名,在開(kāi)發(fā)過(guò)程中,我們經(jīng)常需要根據(jù)不同的環(huán)境來(lái)加載不同的配置文件,本文給大家介紹了SpringBoot項(xiàng)目動(dòng)態(tài)指定配置文件的方法示例,需要的朋友可以參考下2024-12-12
java HttpClient傳輸json格式的參數(shù)實(shí)例講解
這篇文章主要介紹了java HttpClient傳輸json格式的參數(shù)實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01
IDEA 2022 CPU占用100%的問(wèn)題及解決方法
這篇文章主要介紹了IDEA 2022 CPU占用100%問(wèn)題及解決方法,其實(shí)解決方法很簡(jiǎn)單,只需要禁用三個(gè)插件然后重啟idea即可成功解決,需要的朋友可以參考下本文2022-08-08
使用RedisAtomicLong優(yōu)化性能問(wèn)題
這篇文章主要介紹了使用RedisAtomicLong優(yōu)化性能問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11

