Java多線程之Park和Unpark原理
一、基本使用
它們是 LockSupport 類中的方法
// 暫停當前線程 LockSupport.park(); // 恢復某個線程的運行 LockSupport.unpark(暫停線程對象)
應用:先 park 再 unpark
Thread t1 = new Thread(() -> {
log.debug("start...");
sleep(1);
log.debug("park...");
LockSupport.park();
log.debug("resume...");
},"t1");
t1.start();
sleep(2);
log.debug("unpark...");
LockSupport.unpark(t1);
}
14:03:01.438 c.test21: [t1] - start...
14:03:02.444 c.test21: [t1] - park...
14:03:04.399 c.test21: [main] - unpark...
14:03:04.399 c.test21: [t1] - resume...
應用:先upark后park,park不住
package com.concurrent.test4;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
@Slf4j(topic = "c.test21:")
public class Test26 {
public static void main(String[] args) throws InterruptedException{
Thread t1 = new Thread(() -> {
log.debug("start...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("park...");
LockSupport.park();
log.debug("resume...");
},"t1");
t1.start();
log.debug("unpark...");
LockSupport.unpark(t1);
}
}
14:03:35.565 c.test21: [t1] - start...
14:03:35.565 c.test21: [main] - unpark...
14:03:36.572 c.test21: [t1] - park...
14:03:36.572 c.test21: [t1] - resume...
二、特點
與 Object 的 wait & notify 相比
- wait,notify 和 notifyAll 必須配合 Object Monitor 一起使用,而 park,unpark 不必
- park & unpark 是以線程為單位來【阻塞】和【喚醒】線程,而 notify 只能隨機喚醒一個等待線程,notifyAll是喚醒所有等待線程,就不那么【精確】
- park & unpark 可以先 unpark,而 wait & notify 不能先 notify
三、park unpark 原理
每個線程都有自己的一個 Parker 對象,由三部分組成 _counter , _cond 和 _mutex . 打個比喻線程就像一個旅人,Parker 就像他隨身攜帶的背包,條件變量就好比背包中的帳篷。_counter 就好比背包中的備用干糧(0 為耗盡,1 為充足)調(diào)用 park 就是要看需不需要停下來歇息,如果備用干糧耗盡,那么鉆進帳篷歇息. 如果備用干糧充足,那么不需停留,繼續(xù)前進調(diào)用 unpark,就好比令干糧充足.如果這時線程還在帳篷,就喚醒讓他繼續(xù)前進,如果這時線程還在運行,那么下次他調(diào)用 park 時,僅是消耗掉備用干糧,不需停留繼續(xù)前進,因為背包空間有限,多次調(diào)用 unpark 僅會補充一份備用干糧

- 當前線程調(diào)用 Unsafe.park() 方法
- 檢查 _counter ,本情況為 0,這時,獲得 _mutex 互斥鎖
- 線程進入 _cond 條件變量阻塞
- 設置 _counter = 0

- 調(diào)用 Unsafe.unpark(Thread_0) 方法,設置 _counter 為 1
- 喚醒 _cond 條件變量中的 Thread_0
- Thread_0 恢復運行
- 設置 _counter 為 0

- 調(diào)用 Unsafe.unpark(Thread_0) 方法,設置 _counter 為 1
- 當前線程調(diào)用 Unsafe.park() 方法檢查
- _counter ,本情況為 1,這時線程無需阻塞,繼續(xù)運行
- 設置 _counter 為 0
四、park/unpark 原理總結(jié)
park 操作
1.獲取當前線程關聯(lián)的 Parker 對象。
2.將計數(shù)器置為 0,同時檢查計數(shù)器的原值是否為 1,如果是則放棄后續(xù)操作。
3.在互斥量上加鎖。
4.在條件變量上阻塞,同時釋放鎖并等待被其他線程喚醒,當被喚醒后,將重新獲取鎖。
5.當線程恢復至運行狀態(tài)后,將計數(shù)器的值再次置為 0。
釋放鎖。
unpark 操作:
6.獲取目標線程關聯(lián)的 Parker 對象(注意目標線程不是當前線程)。
7.在互斥量上加鎖。
8.將計數(shù)器置為 1。
9.喚醒在條件變量上等待著的線程。
10.釋放鎖。
到此這篇關于Java多線程之Park和Unpark原理的文章就介紹到這了,更多相關Java Park和Unpark原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- Java多線程的具體介紹與使用筆記小結(jié)
- java多線程累加計數(shù)的實現(xiàn)方法
- Java多線程之Interrupt中斷線程詳解
- JAVA多線程中join()方法的使用方法
- Java實現(xiàn)多線程中的靜態(tài)代理模式
- Java進階必備之多線程編程
- java如何實現(xiàn)多線程的順序執(zhí)行
- 總結(jié)java多線程之互斥與同步解決方案
- 如何解決Java多線程死鎖問題
- java多線程創(chuàng)建及線程安全詳解
- Java多線程之線程同步
- Java多線程之ReentrantReadWriteLock源碼解析
- Java多線程之線程的創(chuàng)建
- Java多線程之synchronized關鍵字的使用
- Java多線程之Disruptor入門
- Java基礎之多線程的三種實現(xiàn)方式
- Java多線程之深入理解ReentrantLock
- Java實戰(zhàn)之多線程模擬站點售票
相關文章
SpringSecurity中的Filter Chain(過濾器鏈)
Spring Security的Filter Chain是由一系列過濾器組成的管道,每個過濾器執(zhí)行特定的安全功能,Spring Security能夠提供強大而靈活的安全控制機制,從而保護你的應用程序不受各種網(wǎng)絡安全威脅的侵害,本文介紹SpringSecurity中的Filter Chain,感興趣的朋友跟隨小編一起看看吧2024-06-06
Java內(nèi)存劃分:運行時數(shù)據(jù)區(qū)域
聽說Java運行時環(huán)境的內(nèi)存劃分是挺進BAT的必經(jīng)之路,這篇文章主要給大家介紹了關于Java運行時數(shù)據(jù)區(qū)域(內(nèi)存劃分)的相關資料,需要的朋友可以參考下2021-07-07
Java concurrency線程池之線程池原理(三)_動力節(jié)點Java學院整理
這篇文章主要為大家詳細介紹了Java concurrency線程池之線程池原理第三篇,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06

