精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

国产午夜精品无码| 毛片av在线播放| 免费一级a毛片| 日韩在线观看| 日韩一区二区三区在线观看| www.99riav| 午夜av免费观看| 奇米影视一区二区三区| 欧美成人精品一区二区| 一本色道综合久久欧美日韩精品| 经典三级一区二区| 亚洲男人的天堂在线观看| 精品国产乱码久久久久久久软件| 亚洲免费视频二区| 一区在线免费观看| 亚洲人成自拍网站| 无码国产精品一区二区高潮| 涩涩网在线视频| 亚洲私人黄色宅男| 免费在线一区二区| 国产不卡精品视频| 奇米影视在线99精品| 午夜精品福利视频| 日本黄色片免费观看| 亚洲裸色大胆大尺寸艺术写真| 欧美区在线观看| 日韩在线视频在线观看| www在线视频| 久久久久久久综合狠狠综合| av资源站久久亚洲| 久久久999久久久| 亚洲深夜福利| 在线一区电影| 亚洲成av人**亚洲成av**| 午夜精品亚洲一区二区三区嫩草 | 色老汉一区二区三区| 久久观看最新视频| 午夜免费播放观看在线视频| 91蜜桃视频在线| 国产一区二区三区黄| 精品人妻一区二区三区蜜桃 | 三级做a全过程在线观看| 国产麻豆精品一区二区| 国产精品久久久久久久7电影 | 欧美伊人精品成人久久综合97| 屁屁影院ccyy国产第一页| 一本一道波多野毛片中文在线| 久久久久久久综合日本| 美女主播视频一区| 天堂成人在线| 成人av在线网站| 国产视频在线观看一区| 理论片中文字幕| 成人福利视频在线看| 成人动漫视频在线观看完整版| 国产精品女人久久久| 理论电影国产精品| 成人在线激情视频| 91片黄在线观看喷潮| 另类小说视频一区二区| 成人黄色中文字幕| 国产精品视频一区二区三区,| 日本欧美一区二区三区乱码| 国产精品一区二区黑丝| 色偷偷噜噜噜亚洲男人| 91无套直看片红桃在线观看| 日韩高清欧美| 久久精品中文字幕| 久草视频中文在线| 一本色道精品久久一区二区三区| 91精品国产成人| www五月天com| 久久精品国产第一区二区三区| 成人av番号网| 北条麻妃一二三区| 99久精品国产| 亚洲成人蜜桃| 黄网址在线观看| 亚洲一区二区三区爽爽爽爽爽| 国产freexxxx性播放麻豆| 色偷偷色偷偷色偷偷在线视频| 91久久线看在观草草青青| 久久婷婷综合色| 在线播放一区二区精品视频| 亚洲福利视频久久| 国产精品高清无码在线观看| 四虎成人精品永久免费av九九| 久久夜色精品亚洲噜噜国产mv| 久久精品这里有| 久久久久久色| 亚洲自拍高清视频网站| 头脑特工队2在线播放| 欧美极品少妇xxxxⅹ高跟鞋| 四虎精品欧美一区二区免费| 免费高潮视频95在线观看网站| 欧美主播一区二区三区美女| 国内精品国产三级国产aⅴ久| 老司机aⅴ在线精品导航| 亚洲深夜福利在线| 激情五月婷婷小说| 久久综合五月| 国产精品三区在线| 亚洲s色大片| 欧美日韩加勒比精品一区| 日本激情综合网| 久9re热视频这里只有精品| 中日韩午夜理伦电影免费| 国产性猛交普通话对白| 日本成人在线不卡视频| 国产精品久久九九| 日本三级视频在线播放| 欧美午夜激情小视频| 午夜av中文字幕| 国产成人一区二区三区影院| 欧美第一页在线| 亚洲天堂男人网| 久久久久青草大香线综合精品| 国产日韩欧美大片| 日韩美女在线| 一区二区国产精品视频| 亚洲国产综合久久| 国产福利一区在线| 亚洲国产一区二区三区在线| 亚洲女同志freevdieo| 日韩女优av电影| 懂色av蜜臀av粉嫩av永久| 久久久综合网| 久久精品日韩精品| h片在线观看下载| 欧美一区二区二区| 999精品在线视频| 免费成人小视频| 日本免费高清一区| 在线看片国产福利你懂的| 精品国一区二区三区| 青青草激情视频| 国产一区二区在线视频| 一区二区三区偷拍| 日本久久一区| 日韩亚洲国产中文字幕| 亚洲无码久久久久久久| 中文字幕av资源一区| 亚洲色图38p| 韩日一区二区三区| 日本91av在线播放| 黄色软件在线| 色视频一区二区| 级毛片内射视频| 日本不卡视频一二三区| 亚洲精品成人久久久998| 中文另类视频| 在线播放国产一区中文字幕剧情欧美 | 一区不卡在线观看| 国产精品女同一区二区三区| 日本xxxx黄色| 欧美oldwomenvideos| 91精品国产综合久久香蕉最新版| 色视频在线免费观看| 欧美军同video69gay| 欧美成人777| 成人自拍视频在线| 日本精品免费在线观看| 国产精品日韩精品中文字幕| 国产精品第三页| 毛片在线看网站| 日韩你懂的在线播放| 国产真实的和子乱拍在线观看| 97久久精品人人做人人爽| 国产a级一级片| 成人精品视频| 亚洲free性xxxx护士hd| 7777kkk亚洲综合欧美网站| 亚洲精品久久在线| 成人午夜精品视频| 亚洲精选视频在线| 国产精品无码毛片| 另类人妖一区二区av| 大伊香蕉精品视频在线| 婷婷精品在线| 国产欧美在线观看| 99热99re6国产在线播放| 亚洲人成毛片在线播放| 91精品在线视频观看| 亚洲国产日韩a在线播放| b站大片免费直播| 国产乱子轮精品视频| 自拍日韩亚洲一区在线| 欧美日韩中文一区二区| 99re国产在线播放| 免费看av不卡| 欧美日韩xxxxx| 国产黄色片在线播放| 日韩欧美另类在线| 69视频免费看| 亚洲影院理伦片| 亚洲а∨天堂久久精品2021| 国产丶欧美丶日本不卡视频| www.亚洲天堂网| 欧美成人日韩| 天堂社区 天堂综合网 天堂资源最新版 | 精品美女久久久久久免费| 好吊视频在线观看| 粉嫩高潮美女一区二区三区| 亚洲一区在线不卡| 99热这里只有精品8| 中文字幕一区二区三区最新| 三级精品视频| 999国内精品视频在线| 国产69精品久久| 91精品国产成人www| 91高清在线观看视频| 亚洲一区第一页| 天天操天天插天天射| 欧美一区二区精品久久911| 最新黄色网址在线观看| 精品女厕一区二区三区| 欧美日韩中文字幕在线观看| 日本一区二区动态图| 黄色国产在线观看| 成人毛片视频在线观看| 视频区 图片区 小说区| 奇米精品一区二区三区四区| 91av资源网| 国产精品久久久一区二区| 女人色极品影院| 91成人精品| 一区二区三区免费看| 国产成人三级| 欧美成熟毛茸茸复古| 国产精品玖玖玖在线资源| 亚洲综合小说区| 亚洲精品成人一区| 国产一区在线播放| 国内自拍亚洲| 国产精品香蕉在线观看| 无人区在线高清完整免费版 一区二| 98精品国产高清在线xxxx天堂| 欧美xxx黑人xxx水蜜桃| 欧美激情第1页| 秋霞在线午夜| 久久久噜噜噜久久中文字免| 日本小视频在线免费观看| 九九视频这里只有精品| 91中文在线| 久久久精品欧美| 成人免费网址| 欧美大片在线看| 91豆花视频在线播放| 午夜精品久久17c| 伊人久久在线| 欧美专区在线播放| 亚洲爱爱视频| 国产主播欧美精品| 国产一区二区在线观| 97人人模人人爽人人喊38tv| 999久久精品| 久久久久高清| 狠狠做深爱婷婷综合一区| 性欧美大战久久久久久久免费观看| 日本一区二区三区视频| 中文字幕精品一区日韩| 午夜精品亚洲| 毛片在线视频播放| 石原莉奈在线亚洲三区| 99热一区二区| 国产99久久久国产精品免费看| 久久福利小视频| 久久精品视频免费观看| jizz日本在线播放| 一区二区国产视频| 国产成人精品一区二三区| 欧美亚男人的天堂| 国产www免费观看| 日韩av一区二区在线| 91高清在线视频| 欧美日本啪啪无遮挡网站| 中文字幕在线看片| 国产日本欧美一区二区三区| 成人福利一区| 欧洲一区二区在线观看| 亚洲精品91| 777久久久精品一区二区三区 | 亚洲蜜桃视频| 亚洲中文字幕无码av永久| 久久国产欧美| 免费国偷自产拍精品视频| 97久久精品人人做人人爽| 国产成人免费在线观看视频| 亚洲成人第一页| 一级特黄色大片| 亚洲精美色品网站| 无遮挡动作视频在线观看免费入口| 欧美激情第99页| 国产麻豆一区| 久久超碰亚洲| 欧美在线网址| 精品久久久久久中文字幕2017| 国产很黄免费观看久久| 日韩一区二区a片免费观看| 一区二区在线看| 日本一区二区三区久久| 亚洲国产又黄又爽女人高潮的| 午夜国产福利在线| 91干在线观看| 91久久精品无嫩草影院| 亚洲欧美国产一区二区| 91久久综合| 精产国品一二三区| 亚洲国产成人在线| 午夜精品久久久久久久久久久久久蜜桃 | 久久成人人人人精品欧| 欧美福利在线播放| 国产精品一区二区不卡视频| 天天影视欧美综合在线观看| 一本久道中文无码字幕av| 成人h动漫精品一区二区| 久久高清内射无套| 欧美久久一二三四区| 成人免费在线电影| 国产69久久精品成人| av成人资源| 中国女人做爰视频| 国产一区91精品张津瑜| 国产白丝一区二区三区| 色偷偷久久人人79超碰人人澡| 免费观看国产视频| 欧美激情国内偷拍| 麻豆一区在线| 大桥未久一区二区| 久久99精品久久久久久动态图 | 91精品大全| 国产乱肥老妇国产一区二| 国产不卡一区| 蜜臀久久99精品久久久酒店新书 | 日本不卡一区二区三区四区| 青娱乐精品在线视频| japanese中文字幕| 欧美午夜精品久久久久久人妖| 四虎在线视频免费观看| 97在线观看视频国产| 久久精品亚洲成在人线av网址| 97在线国产视频| 成人av免费在线播放| 日韩激情在线播放| 亚洲激情小视频| 亚洲美女尤物影院| 欧美资源一区| 热久久免费视频| sm捆绑调教视频| 欧美精品自拍偷拍| sm国产在线调教视频| 99久久自偷自偷国产精品不卡| 亚洲视频电影在线| 国产成人av片| 亚洲成av人影院在线观看网| 日韩在线视频观看免费| 91精品国产一区| 国产一区网站| 91精品999| 一区二区三区中文字幕精品精品 | 在线日韩精品视频| 久久青草视频| 欧洲美女和动交zoz0z| 成人午夜精品在线| 久久久久女人精品毛片九一| 一区二区三区视频观看| 四虎精品在线观看| 国产在线观看欧美| 91久色porny| 伊人22222| 欧美激情日韩图片| 台湾色综合娱乐中文网| 污版视频在线观看| 一区二区三区精品视频在线| 天堂а√在线8种子蜜桃视频| 国产精品人成电影在线观看| 欧美91精品| www.色多多| 欧美一级一区二区| 国产伦理精品| 亚洲人一区二区| 成人av高清在线| 中文字幕无线码一区| 久久久久亚洲精品国产| 欧洲grand老妇人| 又黄又色的网站| 欧美亚男人的天堂| 成人免费一区二区三区牛牛| 日韩免费毛片| 懂色中文一区二区在线播放| 国产午夜无码视频在线观看| 九九热这里只有精品6| 超碰成人久久| 久久性爱视频网站| 欧美日韩免费一区二区三区| 精品极品在线| 国产精品av免费观看| 国产日本欧洲亚洲| 国产精品视频免费在线| 在线一区电影|