日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
都已經(jīng)2023年了,你還不知道StampedLock嗎?

?概述

想到讀寫(xiě)鎖,大家第一時(shí)間想到的可能是ReentrantReadWriteLock?。實(shí)際上,在jdk8以后,java提供了一個(gè)性能更優(yōu)越的讀寫(xiě)鎖并發(fā)類(lèi)StampedLock?,該類(lèi)的設(shè)計(jì)初衷是作為一個(gè)內(nèi)部工具類(lèi),用于輔助開(kāi)發(fā)其它線程安全組件,用得好,該類(lèi)可以提升系統(tǒng)性能,用不好,容易產(chǎn)生死鎖和其它莫名其妙的問(wèn)題。本文主要和大家一起學(xué)習(xí)下StampedLock的功能和使用。

目前創(chuàng)新互聯(lián)公司已為上千的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)站空間、網(wǎng)站托管、服務(wù)器托管、企業(yè)網(wǎng)站設(shè)計(jì)、愛(ài)輝網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶(hù)導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶(hù)和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。

StampedLock介紹

StampedLock?的狀態(tài)由版本和模式組成。鎖獲取方法返回一個(gè)戳,該戳表示并控制對(duì)鎖狀態(tài)的訪問(wèn)。StampedLock提供了3種模式控制訪問(wèn)鎖:

寫(xiě)模式

獲取寫(xiě)鎖,它是獨(dú)占的,當(dāng)鎖處于寫(xiě)模式時(shí),無(wú)法獲得讀鎖,所有樂(lè)觀讀驗(yàn)證都將失敗。

  • writeLock(): 阻塞等待獨(dú)占獲取鎖,返回一個(gè)戳, 如果是0表示獲取失敗。
  • tryWriteLock():嘗試獲取一個(gè)寫(xiě)鎖,返回一個(gè)戳, 如果是0表示獲取失敗。
  • long tryWriteLock(long time, TimeUnit unit): 嘗試獲取一個(gè)獨(dú)占寫(xiě)鎖,可以等待一段事件,返回一個(gè)戳, 如果是0表示獲取失敗。
  • long writeLockInterruptibly(): 試獲取一個(gè)獨(dú)占寫(xiě)鎖,可以被中斷,返回一個(gè)戳, 如果是0表示獲取失敗。
  • unlockWrite(long stamp):釋放獨(dú)占寫(xiě)鎖,傳入之前獲取的戳。
  • tryUnlockWrite():如果持有寫(xiě)鎖,則釋放該鎖,而不需要戳值。這種方法可能對(duì)錯(cuò)誤后的恢復(fù)很有用。
long stamp = lock.writeLock();
try {
....
} finally {
lock.unlockWrite(stamp);
}

讀模式

悲觀的方式后去非獨(dú)占讀鎖。

  • readLock(): 阻塞等待獲取非獨(dú)占的讀鎖,返回一個(gè)戳, 如果是0表示獲取失敗。
  • tryReadLock():嘗試獲取一個(gè)讀鎖,返回一個(gè)戳, 如果是0表示獲取失敗。
  • long tryReadLock(long time, TimeUnit unit): 嘗試獲取一個(gè)讀鎖,可以等待一段事件,返回一個(gè)戳, 如果是0表示獲取失敗。
  • long readLockInterruptibly(): 阻塞等待獲取非獨(dú)占的讀鎖,可以被中斷,返回一個(gè)戳, 如果是0表示獲取失敗。
  • unlockRead(long stamp):釋放非獨(dú)占的讀鎖,傳入之前獲取的戳。
  • tryUnlockRead():如果讀鎖被持有,則釋放一次持有,而不需要戳值。這種方法可能對(duì)錯(cuò)誤后的恢復(fù)很有用。
long stamp = lock.readLock();
try {
....
} finally {
lock.unlockRead(stamp);
}

樂(lè)觀讀模式

樂(lè)觀讀也就是若讀的操作很多,寫(xiě)的操作很少的情況下,你可以樂(lè)觀地認(rèn)為,寫(xiě)入與讀取同時(shí)發(fā)生幾率很少,因此不悲觀地使用完全的讀取鎖定,程序可以查看讀取資料之后,是否遭到寫(xiě)入執(zhí)行的變更,再采取后續(xù)的措施(重新讀取變更信息,或者拋出異常) ,這一個(gè)小小改進(jìn),可大幅度提高程序的吞吐量。

StampedLock?支持 tryOptimisticRead()方法,讀取完畢后做一次戳校驗(yàn),如果校驗(yàn)通過(guò),表示這期間沒(méi)有其他線程的寫(xiě)操作,數(shù)據(jù)可以安全使用,如果校驗(yàn)沒(méi)通過(guò),需要重新獲取讀鎖,保證數(shù)據(jù)一致性。

  • tryOptimisticRead(): 返回稍后可以驗(yàn)證的戳記,如果獨(dú)占鎖定則返回零。
  • boolean validate(long stamp): 如果自給定戳記發(fā)行以來(lái)鎖還沒(méi)有被獨(dú)占獲取,則返回true。
long stamp = lock.tryOptimisticRead();
// 驗(yàn)戳
if(!lock.validate(stamp)){
// 鎖升級(jí)
}

此外,StampedLock 提供了api實(shí)現(xiàn)上面3種方式進(jìn)行轉(zhuǎn)換:

  • long tryConvertToWriteLock(long stamp)

如果鎖狀態(tài)與給定的戳記匹配,則執(zhí)行以下操作之一。如果戳記表示持有寫(xiě)鎖,則返回它。或者,如果是讀鎖,如果寫(xiě)鎖可用,則釋放讀鎖并返回寫(xiě)戳記?;蛘?,如果是樂(lè)觀讀,則僅在立即可用時(shí)返回寫(xiě)戳記。該方法在所有其他情況下返回零

  • long tryConvertToReadLock(long stamp)

如果鎖狀態(tài)與給定的戳記匹配,則執(zhí)行以下操作之一。如果戳記表示持有寫(xiě)鎖,則釋放它并獲得讀鎖?;蛘撸绻亲x鎖,返回它。或者,如果是樂(lè)觀讀,則僅在立即可用時(shí)才獲得讀鎖并返回讀戳記。該方法在所有其他情況下返回零。

  • long tryConvertToOptimisticRead(long stamp)

如果鎖狀態(tài)與給定的戳記匹配,那么如果戳記表示持有鎖,則釋放它并返回一個(gè)觀察戳記?;蛘撸绻菢?lè)觀讀,則在驗(yàn)證后返回它。該方法在所有其他情況下返回0,因此作為“tryUnlock”的形式可能很有用。

演示例子

下面用一個(gè)例子演示下StampedLock的使用,例子來(lái)源jdk中的javadoc。

@Slf4j
@Data
public class Point {
private double x, y;
private final StampedLock sl = new StampedLock();

void move(double deltaX, double throws{
//涉及對(duì)共享資源的修改,使用寫(xiě)鎖-獨(dú)占操作
long stamp = sl.writeLock();
log.info("writeLock lock success");
Thread.sleep(500);
try {
x += deltaX;
y += deltaY;
} finally {
sl.unlockWrite(stamp);
log.info("unlock write lock success");
}
}

/**
* 使用樂(lè)觀讀鎖訪問(wèn)共享資源
* 注意:樂(lè)觀讀鎖在保證數(shù)據(jù)一致性上需要拷貝一份要操作的變量到方法棧,并且在操作數(shù)據(jù)時(shí)候可能其他寫(xiě)線程已經(jīng)修改了數(shù)據(jù),
* 而我們操作的是方法棧里面的數(shù)據(jù),也就是一個(gè)快照,所以最多返回的不是最新的數(shù)據(jù),但是一致性還是得到保障的。
*
* @return
*/
double distanceFromOrigin() throws{
long stamp = sl.tryOptimisticRead(); // 使用樂(lè)觀讀鎖
log.info("tryOptimisticRead lock success");
// 睡一秒中
Thread.sleep(1000);
double currentX = x, currentY = y; // 拷貝共享資源到本地方法棧中
if (!sl.validate(stamp)) { // 如果有寫(xiě)鎖被占用,可能造成數(shù)據(jù)不一致,所以要切換到普通讀鎖模式
log.info("validate stamp error");
stamp = sl.readLock();
log.info("readLock success");
try {
currentX = x;
currentY = y;
} finally {
sl.unlockRead(stamp);
log.info("unlock read success");
}
}
return Math.sqrt(currentX * currentX + currentY * currentY);
}

void moveIfAtOrigin(double newX, double{ // upgrade
// Could instead start with optimistic, not read mode
long stamp = sl.readLock();
try {
while (x == 0.0 && y == 0.0) {
long ws = sl.tryConvertToWriteLock(stamp); //讀鎖轉(zhuǎn)換為寫(xiě)鎖
if (ws != 0L) {
stamp = ws;
x = newX;
y = newY;
break;
} else {
sl.unlockRead(stamp);
stamp = sl.writeLock();
}
}
} finally {
sl.unlock(stamp);
}
}
}

測(cè)試用例:

@Test
public void testStamped() throws InterruptedException {
Point point = new Point();
point.setX(1);
point.setY(2);
// 線程0 執(zhí)行了樂(lè)觀讀
Thread thread0 = new Thread(() -> {
try {
// 樂(lè)觀讀
point.distanceFromOrigin();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "thread-0");
thread0.start();

Thread.sleep(500);
// 線程1 執(zhí)行寫(xiě)鎖
Thread thread1 = new Thread(() -> {
// 樂(lè)觀讀
try {
point.move(3, 4);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "thread-1");
thread1.start();

thread0.join();
thread1.join();
}

結(jié)果:

性能對(duì)比

正是由于StampedLock?的樂(lè)觀讀模式,早就StampedLock的高性能和高吞吐量,那么具體的性能提高有多少呢?

下圖是和ReadWritLock相比,在一個(gè)線程情況下,讀速度是其4倍左右,寫(xiě)是1倍。

下圖是16個(gè)線程情況下,讀性能是其幾十倍,寫(xiě)性能也是近10倍左右:

下圖是吞吐量提高:

那么這樣是不是說(shuō)StampedLock?可以全方位的替代ReentrantReadWriteLock?, 答案是否定的,StampedLock?相對(duì)于ReentrantReadWriteLock有下面兩個(gè)問(wèn)題:

  • 不支持條件變量Condition
  • 不支持可重入

所以最終選擇StampedLock?還是ReentrantReadWriteLock,還是要看具體的業(yè)務(wù)場(chǎng)景。

總結(jié)

本文主要講解了StampedLock?的功能和使用,至于原理,StampedLock雖然不像其它鎖一樣定義了內(nèi)部類(lèi)來(lái)實(shí)現(xiàn)AQS框架,但是StampedLock的基本實(shí)現(xiàn)思路還是利用CLH隊(duì)列進(jìn)行線程的管理,通過(guò)同步狀態(tài)值來(lái)表示鎖的狀態(tài)和類(lèi)型,具體的源碼實(shí)現(xiàn)大家感興趣的自己可以追蹤看看。


本文標(biāo)題:都已經(jīng)2023年了,你還不知道StampedLock嗎?
新聞來(lái)源:http://www.dlmjj.cn/article/dpishde.html