精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

ReentrantLock可重入、可打斷、鎖超時實現原理

開發 前端
ReentrantLock還具備鎖超時的能力,調用tryLock(long timeout, TimeUnit unit)方法,在給定時間內獲取鎖,獲取不到就退出,這也是synchronized沒有的功能。

?概述

前面講解了ReentrantLock加鎖和解鎖的原理實現,但是沒有闡述它的可重入、可打斷以及超時獲取鎖失敗的原理,本文就重點講解這三種情況。建議大家先看下這篇文章了解下ReentrantLock加鎖的基本原理,圖解ReentrantLock公平鎖和非公平鎖實現原理。

可重入

可重入是指一個線程如果獲取了鎖,那么它就是鎖的主人,那么它可以再次獲取這把鎖,這種就是理解為重入,簡而言之,可以重復獲取同一把鎖,不會造成阻塞,舉個例子如下:

@Test
public void testRepeatLock() {
ReentrantLock reentrantLock = new ReentrantLock();
// 第一次獲取鎖
reentrantLock.lock();
try {
System.out.println(Thread.currentThread().getName() + " first get lock");
// 再次獲取鎖
tryAgainLock(reentrantLock);
}finally {
reentrantLock.unlock();
}
}

public void tryAgainLock(ReentrantLock reentrantLock) {
// 第2次獲取鎖
reentrantLock.lock();
try {
System.out.println(Thread.currentThread().getName() + " second get lock");
}finally {
reentrantLock.unlock();
}
}

圖片

  • 同一個線程使用ReentrantLock多次獲取鎖,不會阻塞
  • 申請幾把鎖,最后需要解除幾把鎖

那你知道是怎么實現的嗎?

概述的文章中已經講解了ReentrantLock整個的加鎖和解鎖的過程,可重入實現就在其中,這里著重關注下申請鎖的方法tryAcquire,最終會調用nonfairTryAcquire方法。

圖片

如果已經有線程獲得了鎖, 并且占用鎖的線程是當前線程, 表示【發生了鎖重入】,上圖的1步驟

計算出沖入的次數nextc等于當前次數+新增次數,acquires等于1

更新 state 的值,這里不使用 cas 是因為當前線程正在持有鎖,所以這里的操作相當于在一個管程內, 然后返回ture,表明再次申請鎖成功。

可打斷

ReentrantLock相比于synchronized加鎖一大優勢是可打斷,那么什么是可打斷呢?ReentrantLock通過lockInterruptibly()?加鎖,如果一直獲取不到鎖,可以通過調用線程的interrupt()提前終止線程。舉個例子:

@Test
public void testInterrupt() throws InterruptedException {
ReentrantLock lock = new ReentrantLock();

// 主線程普通加鎖
System.out.println("主線程優先獲取鎖");
lock.lock();
try {
// 創建子線程
Thread t1 = new Thread(() -> {
try {
System.out.println("t1嘗試獲取打斷鎖");
lock.lockInterruptibly();
} catch (InterruptedException e) {
System.out.println("t1沒有獲取到鎖,被打斷,直接返回");
return;
}
try {
System.out.println("t1成功獲取鎖");
} finally {
System.out.println("t1釋放鎖");
lock.unlock();
}
}, "t1");
t1.start();
Thread.sleep(2000);
System.out.println("主線程進行打斷鎖");
t1.interrupt();
} finally {
// 主線程解鎖
System.out.println("主線程優先釋放鎖");
lock.unlock();
}
}

圖片

  • 通過lockInterruptibly()?方法獲取鎖期間,可以通過線程的interrupt()方法進行中斷,跳出阻塞。
  • 通過lock()?方法獲取鎖,不會響應interrupt()方法的中斷。

接下來我們看看它的實現原理。

public void lockInterruptibly() throws InterruptedException {    
sync.acquireInterruptibly(1);
}
public final void acquireInterruptibly(int arg) {
// 被其他線程打斷了直接返回 false
if (Thread.interrupted())
throw new InterruptedException();
if (!tryAcquire(arg))
// 沒獲取到鎖,進入這里
doAcquireInterruptibly(arg);
}

先判斷一次線程是否中斷了,是的話,直接拋出中斷異常。

如果沒有獲取鎖,調用doAcquireInterruptibly()方法。

private void doAcquireInterruptibly(int arg) throws InterruptedException {
// 封裝當前線程,加入到隊列中
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
// 自旋
for (;;) {
// shouldParkAfterFailedAcquire判斷是否需要阻塞等待
// parkAndCheckInterrupt方法是阻塞線程,返回true,表示線程被中斷了
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())
// 【在 park 過程中如果被 interrupt 會拋出異常】, 而不會再次進入循環獲取鎖后才完成打斷效果
throw new InterruptedException();
}
} finally {
// 拋出異常前會進入這里
if (failed)
// 取消當前線程的節點
cancelAcquire(node);
}
}

addWaiter將當前線程封裝成節點,加入到隊列中。

shouldParkAfterFailedAcquire()方法判斷如果前一個節點的等待狀態時-1,則返回true,表示當前線程需要阻塞。

parkAndCheckInterrupt()?方法是阻塞線程,返回true,表示線程被中斷了,拋出InterruptedException異常。

最后調用cancelAcquire()方法,將當前節點狀態設置為cancel取消狀態。

// 取消節點出隊的邏輯
private void cancelAcquire(Node node) {
// 判空
if (node == null)
return;
// 把當前節點封裝的 Thread 置為空
node.thread = null;
// 獲取當前取消的 node 的前驅節點
Node pred = node.prev;
// 前驅節點也被取消了,循環找到前面最近的沒被取消的節點
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;

// 獲取前驅節點的后繼節點,可能是當前 node,也可能是 waitStatus > 0 的節點
Node predNext = pred.next;

// 把當前節點的狀態設置為 【取消狀態 1
node.waitStatus = Node.CANCELLED;

// 條件成立說明當前節點是尾節點,把當前節點的前驅節點設置為尾節點
if (node == tail && compareAndSetTail(node, pred)) {
// 把前驅節點的后繼節點置空,這里直接把所有的取消節點出隊
compareAndSetNext(pred, predNext, null);
} else {
// 說明當前節點不是 tail 節點
int ws;
// 條件一成立說明當前節點不是 head.next 節點
if (pred != head &&
// 判斷前驅節點的狀態是不是 -1,不成立說明前驅狀態可能是 0 或者剛被其他線程取消排隊了
((ws = pred.waitStatus) == Node.SIGNAL ||
// 如果狀態不是 -1,設置前驅節點的狀態為 -1
(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
// 前驅節點的線程不為null
pred.thread != null) {

Node next = node.next;
// 當前節點的后繼節點是正常節點
if (next != null && next.waitStatus <= 0)
// 把 前驅節點的后繼節點 設置為 當前節點的后繼節點,【從隊列中刪除了當前節點】
compareAndSetNext(pred, predNext, next);
} else {
// 當前節點是 head.next 節點,喚醒當前節點的后繼節點
unparkSuccessor(node);
}
node.next = node; // help GC
}
}

鎖超時

ReentrantLock還具備鎖超時的能力,調用tryLock(long timeout, TimeUnit unit)方法,在給定時間內獲取鎖,獲取不到就退出,這也是synchronized沒有的功能。

@Test
public void testLockTimeout() throws InterruptedException {
ReentrantLock lock = new ReentrantLock();
Thread t1 = new Thread(() -> {
try {
// 調用tryLock獲取鎖
if (!lock.tryLock(2, TimeUnit.SECONDS)) {
System.out.println("t1獲取不到鎖");
return;
}
} catch (InterruptedException e) {
System.out.println("t1被打斷,獲取不到鎖");
return;
}
try {
System.out.println("t1獲取到鎖");
} finally {
lock.unlock();
}
}, "t1");
// 主線程加鎖
lock.lock();
System.out.println("主線程獲取到鎖");

t1.start();
Thread.sleep(3000);
try {
System.out.println("主線程釋放了鎖");
} finally {
lock.unlock();
}
}

那這個原理實現是什么樣的呢?

public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
// 調用tryAcquireNanos方法
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}

public final boolean tryAcquireNanos(int arg, long nanosTimeout) {
if (Thread.interrupted())
throw new InterruptedException();
// tryAcquire 嘗試一次,獲取不到的話調用doAcquireNanos方法
return tryAcquire(arg) || doAcquireNanos(arg, nanosTimeout);
}

protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
private boolean doAcquireNanos(int arg, long nanosTimeout) {    
if (nanosTimeout <= 0L)
return false;
// 獲取最后期限的時間戳
final long deadline = System.nanoTime() + nanosTimeout;
// 將當前線程添加到隊列中
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
// 自旋
for (;;) {
// 獲取前驅節點
final Node p = node.predecessor();
// 前驅節點是head,嘗試獲取鎖
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return true;
}
// 計算還需等待的時間
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0L) //時間已到
return false;
if (shouldParkAfterFailedAcquire(p, node) &&
// 如果 nanosTimeout 大于該值,才有阻塞的意義,否則直接自旋會好點
nanosTimeout > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
// 【被打斷會報異常】
if (Thread.interrupted())
throw new InterruptedException();
}
}
}

如果nanosTimeout小于0,表示到了指定時間沒有獲取鎖成功,返回false

如果 nanosTimeout 大于spinForTimeoutThreshold,值為1000L,進行阻塞。因為時間太短阻塞沒有意義,否則直接自旋會好點。

總結

本文主要從使用到原理講解了ReentrantLock鎖的可重入、可打斷和鎖超時的特性,希望對大家有幫助。

責任編輯:武曉燕 來源: JAVA旭陽
相關推薦

2021-05-11 14:50:21

ReentrantLo可重入鎖Java

2024-01-30 08:41:33

線程執行Redis分布式鎖

2021-12-15 07:49:22

Go語言設計

2020-06-15 08:15:47

分布式鎖系統

2021-07-08 09:21:17

ZooKeeper分布式鎖 Curator

2021-06-27 21:24:55

RedissonJava數據

2020-10-08 18:49:47

函數可重入不可重入

2021-03-11 08:55:47

JavaUser對象

2017-03-08 16:25:54

Linux多線程函數

2025-07-28 02:00:00

Java并發開發

2021-07-10 10:02:30

ZooKeeperCurator并發

2022-12-26 00:00:04

公平鎖非公平鎖

2020-11-10 07:46:58

函數printf 數據

2021-07-09 06:48:31

ZooKeeperCurator源碼

2020-08-24 08:13:25

非公平鎖源碼

2023-09-12 13:48:47

2023-04-06 00:15:03

JavaReentrantL線程

2024-02-04 09:29:07

Redis數據庫

2011-11-23 10:09:19

Java線程機制

2021-01-28 05:17:01

并發包JDK
點贊
收藏

51CTO技術棧公眾號

久久精品视频8| 亚洲久久中文字幕| 人妻偷人精品一区二区三区| 亚洲欧洲一级| 国产香蕉精品视频一区二区三区| 狠狠躁狠狠躁视频专区| 二区三区在线观看| 不卡视频一二三| 国产91在线播放| 国产免费一区二区三区四区| 国产精品极品在线观看| 一本大道久久a久久综合| 亚洲看片网站| 国产黄色高清视频| 久久亚洲影院| 免费91麻豆精品国产自产在线观看| 妖精视频一区二区| 91在线亚洲| 亚洲自拍偷拍麻豆| 四虎影院一区二区三区| 亚洲精品18p| 可以免费看不卡的av网站| 久久伊人精品视频| 91成人破解版| 一区二区中文字幕在线观看| 色94色欧美sute亚洲13| 国产亚洲精品久久久久久久| 国产鲁鲁视频在线观看免费| 成人黄色a**站在线观看| 国产精品男人爽免费视频1| 欧美成人三级视频| 日韩极品一区| 国产视频精品一区二区三区| 成人三级做爰av| 成人在线视频免费看| 欧美日韩国产在线| 国产乱子伦精品无码专区| 97电影在线观看| 久久亚洲精品小早川怜子| 99国产在线视频| 国产又黄又粗又硬| 日韩国产欧美在线视频| 96精品视频在线| 国产亚洲小视频| 亚洲天堂免费| 久久亚洲综合国产精品99麻豆精品福利| 欧洲女同同性吃奶| 欧美电影免费网站| 亚洲国产成人精品久久| 国产乱淫av麻豆国产免费| 亚洲热av色在线播放| 欧美色图12p| 国产一区亚洲二区三区| 亚洲天堂电影| 日韩欧美国产高清91| 国产在线精品91| 97天天综合网| 天天免费综合色| 国产欧美日韩网站| 91视频欧美| 亚洲高清视频在线| 国产69精品久久久久999小说| 在线免费观看污| 一区二区视频在线| 国产精品igao激情视频| 男女在线视频| 亚洲成在线观看| 乱妇乱女熟妇熟女网站| 成人动漫一区| 欧洲另类一二三四区| 亚洲第一狼人区| 四虎国产精品免费久久| 日韩午夜精品视频| 秘密基地免费观看完整版中文 | 国产三级日本三级在线播放| 超级碰碰久久| 精品视频色一区| 污色网站在线观看| 日韩精品成人| 精品国产伦一区二区三区观看体验| 女性生殖扒开酷刑vk| 卡一精品卡二卡三网站乱码| 精品亚洲一区二区三区在线观看| 精品人妻一区二区三区视频| 日本电影一区二区| 久久影院中文字幕| 日韩高清免费av| 久久精品综合| 91在线视频成人| 黄色av一区二区三区| 久久综合色天天久久综合图片| 欧美一区二区三区四区五区六区| 亚洲1卡2卡3卡4卡乱码精品| 亚洲一区二区成人在线观看| 六月丁香婷婷激情| 国产亚洲精品精品国产亚洲综合| 日韩一区二区三区高清免费看看 | 国模大尺度视频一区二区| 亚洲成人激情图| 谁有免费的黄色网址| 中文字幕一区二区av| 性色av一区二区三区| 中文字幕在线视频免费| 丁香一区二区三区| 日日夜夜精品网站| 波多野结衣精品| 欧美日韩在线电影| 久久人妻少妇嫩草av无码专区| 奇米狠狠一区二区三区| 欧美激情aaaa| 日本免费精品视频| 成人一级片网址| 亚洲一区不卡在线| 日韩激情电影| 欧美一区二区成人6969| 亚洲久久久久久久| 伊人久久成人| 成人中文字幕在线观看| 国产在线观看免费| 亚洲成a人v欧美综合天堂下载 | 日本一区二区不卡在线| 美女视频网站黄色亚洲| 久久伦理网站| 高清电影在线免费观看| 欧美群妇大交群中文字幕| 亚洲熟女乱综合一区二区三区| 亚洲国产日韩欧美在线| 国产精品美女免费| 日本一区二区三区在线观看视频| 一区二区三区色| 天堂视频免费看| 精品国产一区探花在线观看| 91精品国产高清久久久久久久久| japanese国产| 中文字幕一区二区三区在线播放| 欧美日韩在线免费播放| 欧美日韩夜夜| 97国产真实伦对白精彩视频8| 99国产揄拍国产精品| 国产精品女主播av| 免费看黄色一级大片| 先锋影音国产精品| 91av中文字幕| 深夜福利免费在线观看| 五月天亚洲精品| av漫画在线观看| 一区在线免费观看| 国产精品乱码视频| 国模雨婷捆绑高清在线| 精品国产人成亚洲区| 免费中文字幕视频| 国产mv日韩mv欧美| 久久99久久久久久| 精品国产18久久久久久洗澡| 久久免费国产视频| 少妇精品高潮欲妇又嫩中文字幕 | 欧美日韩中文字幕在线播放| 精品午夜视频| 欧美成人在线网站| 亚洲AV无码一区二区三区少妇| 亚洲女厕所小便bbb| 国产亚洲色婷婷久久| 欧美三级视频| 国内一区在线| 日韩大尺度黄色| 亚洲偷熟乱区亚洲香蕉av| 中文字幕精品一区二区精| 99久久99久久精品免费观看| 成年人午夜视频在线观看 | 精品一区二区三区在线观看| 中文字幕色一区二区| 日韩国产在线不卡视频| 97在线免费观看| 国产经典自拍视频在线观看| 欧美日韩国产经典色站一区二区三区| 香蕉久久久久久久| 国产精品一区二区果冻传媒| 欧美图片激情小说| 免费成人av| 成人女保姆的销魂服务| 国产第一页在线视频| 亚洲美女av在线播放| 久久久999久久久| 亚洲视频狠狠干| 日韩www视频| 奇米影视在线99精品| 久久av喷吹av高潮av| 国产精品超碰| 国产精品久久久久久网站| 国产区在线观看| 亚洲精品国偷自产在线99热| 中文字幕精品在线观看| 亚洲综合色噜噜狠狠| 无码人妻aⅴ一区二区三区| 捆绑紧缚一区二区三区视频| 日本aa在线观看| 精品久久影院| 国产经典一区二区三区| 电影亚洲一区| 国内精品久久久久久久| 啊v视频在线| 欧美精品一区二区三区久久久| 日韩不卡高清视频| 亚洲国产乱码最新视频| 极品尤物一区二区| 99在线精品观看| 亚洲最大天堂网| 亚洲在线一区| 男人c女人视频| 欧美日韩有码| 极品尤物一区二区三区| 亚洲成人av观看| 91精品国产91久久久久久| 欧美极品另类| 亚洲人成绝费网站色www| 精品久久久中文字幕人妻| 欧美日韩在线不卡| 国偷自拍第113页| 怡红院av一区二区三区| 大吊一区二区三区| 久久先锋影音av鲁色资源网| 日本性生活一级片| 国产揄拍国内精品对白| 天天天干夜夜夜操| 免费日韩一区二区| 妞干网在线观看视频| 中文字幕乱码亚洲无线精品一区| 视频一区在线免费观看| 中文有码一区| 国模精品娜娜一二三区| 6080成人| 亚洲伊人久久大香线蕉av| 欧美成人高清视频在线观看| 日韩免费观看高清| 大胆人体一区| 欧美一区二区三区……| 极品在线视频| 午夜欧美不卡精品aaaaa| 日韩特级毛片| 欧美国产精品日韩| 污污网站在线看| 欧美噜噜久久久xxx| 中日韩高清电影网| 欧美精品免费在线| 青草视频在线免费直播| 九九精品视频在线| 污污网站在线看| 欧美激情一区二区久久久| 欧美xxxx性xxxxx高清| 久久69精品久久久久久久电影好| 国产精品扒开做爽爽爽的视频| 久久精品最新地址| 成人日日夜夜| 欧美另类第一页| 99热99re6国产在线播放| 久久人人爽人人爽人人片av高请 | 成人中文视频| 亚洲精品中文字幕在线| 国产精品99在线观看| 国产成人精品免费看在线播放| 久久久久国产精品| 国产人妻人伦精品| 在线精品一区| 国产91在线视频观看| 久久中文字幕一区二区三区| 欧美精品无码一区二区三区| 蜜臀久久99精品久久久久久9| 天堂一区在线观看| 国产一区在线观看视频| 日本美女视频网站| 久久一区二区视频| 国产在线免费av| 一区二区三区 在线观看视频| 国产在线视频第一页| 欧美日韩国产影院| 中文字幕+乱码+中文字幕明步| 7777女厕盗摄久久久| www.精品视频| 日韩精品在线视频| 91欧美在线视频| 欧美俄罗斯乱妇| 三上悠亚激情av一区二区三区| 国产精品美女久久久久av超清| 欧美久久亚洲| 久久av免费观看| 久久精品高清| 精品丰满人妻无套内射| 日韩制服丝袜先锋影音| 亚洲自拍第三页| 91亚洲国产成人精品一区二三| 亚洲av无码一区二区三区人| 亚洲欧美另类小说| 五月天综合激情网| 91精品在线免费| 亚洲日本国产精品| 久久天天躁夜夜躁狠狠躁2022| bl视频在线免费观看| 国产精品视频永久免费播放| 日韩欧美中文在线观看| 欧美亚洲另类久久综合| 午夜久久99| 999精彩视频| 成人黄色a**站在线观看| 日韩一级片在线免费观看| 亚洲国产精品久久久久婷婷884 | 日韩精品一区二区三区在线播放| 日av在线播放| 欧美精品亚州精品| 福利视频一区| 久久99精品久久久久久青青日本| 日韩在线精品| 国产91在线视频观看| 国产黑丝在线一区二区三区| 人妻精品久久久久中文| 亚洲电影中文字幕在线观看| 91免费视频播放| 亚洲欧洲国产精品| 国产免费拔擦拔擦8x高清在线人| 国产专区欧美专区| 国产精品一区2区3区| 久久久亚洲国产精品| 激情综合色综合久久| 性欧美精品中出| 五月天婷婷综合| 亚洲欧美高清视频| 两个人的视频www国产精品| 久久69成人| 日韩欧美在线观看强乱免费| 中日韩视频在线观看| 国产午夜在线一区二区三区| 国产精品电影院| 欧美性受xxx黑人xyx性爽| 亚洲欧美国产高清va在线播| а√天堂8资源在线| 波多野结衣精品久久| 亚洲欧美日韩高清在线| 一女二男3p波多野结衣| 国产精品欧美综合在线| 久久永久免费视频| 亚洲深夜福利视频| 亚洲黄色网址| 欧美日韩一区在线观看视频| 国产精品毛片| 日韩av一二区| 欧美午夜片欧美片在线观看| 视频二区在线| 欧美在线激情网| 免费av一区| 亚洲最大综合网| 91麻豆免费看| 国产一区二区视频在线观看免费| 欧美日韩高清一区二区三区| 最新av网站在线观看| 国产日本欧美一区| 久久看人人摘| 久久久三级国产网站| 国产小视频自拍| 在线视频国产一区| 日本中文字幕一区二区有码在线| 欧美一级视频免费在线观看| 韩国女主播一区二区三区| 国产毛片视频网站| 99国产精品视频免费观看| 久久丫精品久久丫| 亚洲丁香久久久| 国产蜜臀在线| 精品欧美一区二区在线观看视频 | 国产欧美一区二区精品性| 成人免费一级片| 不卡av电影院| 国内精品国产成人国产三级粉色 | 久久精品国产亚洲一区二区三区| 五月天精品在线| 7777精品伊人久久久大香线蕉经典版下载| 国产在线看片| 国产精品一区二区三区在线观| 亚洲一区网站| 久久日免费视频| 日韩一区二区视频| 蜜桃麻豆影像在线观看| 色噜噜狠狠色综合网| 国产一区二区精品久久91| 日本三级网站在线观看| 亚洲人成网站色ww在线| 在线观看欧美| 鲁一鲁一鲁一鲁一色| 中文字幕免费不卡在线| 亚洲精选一区二区三区| 日本不卡高字幕在线2019| 水蜜桃久久夜色精品一区| 亚洲精品久久一区二区三区777 | 欧美成人国产va精品日本一级| ccyy激情综合| 成年人黄色片视频| 亚洲激情图片一区| 欧美69xxxxx| 91精品婷婷国产综合久久蝌蚪| 免费日韩视频| 精品少妇久久久| 一区二区三区四区视频|