欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java?LockSupport實現(xiàn)原理示例解析

 更新時間:2023年01月09日 09:19:53   作者:小海編碼日記  
這篇文章主要為大家介紹了java?LockSupport實現(xiàn)原理示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

引言

前文中了解到AQS借助LockSupport.park和LockSupport.unpark完成線程的阻塞和喚醒,那么LockSupport內(nèi)部又是怎么實現(xiàn)的?這是一個什么類?

LockSupport是用于使用鎖阻塞線程的基礎實現(xiàn),是其他同步類的基礎,這個類為每個使用它的線程關聯(lián)一個許可證(有點類似于Semaphore),如果許可證可用,線程調(diào)用park方法時會立即返回,線程正常執(zhí)行,否則當前線程阻塞,直到有其他線程調(diào)用unpark使得許可證可用,此時線程被喚醒,再次嘗試獲取許可證,其內(nèi)部定義的park和unpark方法提供了阻塞和解決阻塞的基本實現(xiàn)。

LockSupport常見函數(shù)

如下表所示:

函數(shù)名稱說明備注
void park()阻塞當前線程在下列情況發(fā)生時喚醒: 1.調(diào)用unpark函數(shù),釋放該線程的許可; 2.該線程被中斷; 3.設置的阻塞超時時間耗盡; 4.到達設置的指定時間
void park(Object blocker)使用指定的blocker對象阻塞當前線程喚醒條件,park中已說明
void parkNanos(long nanos)阻塞當前線程直到超時時間耗盡,nanos為指定的超時時間喚醒條件,park中已說明
void parkNanos(Object blocker, long nanos)在超時時間耗盡前,使用指定的blocker對象阻塞當前線程,如果在到達超時時間后,許可仍不可用,則結束阻塞喚醒條件,park中已說明
void parkUntil(long deadline)在指定時間前,阻塞該線程,如果在到達指定時間后,許可仍不可用,則結束阻塞喚醒條件,park中已說明
void parkUntil(Object blocker, long deadline)在指定時間前,使用指定的對象阻塞該線程,如果在到達指定時間后,許可仍不可用,則結束阻塞喚醒條件,park中已說明
void unpark(Thread thread)用于喚醒傳入的在阻塞中的線程/
Object getBlocker(Thread t)獲取當前線程的阻塞對象/
void setBlocker(Thread t, Object arg)使用指定對象為線程設置阻塞對象/

LockSupport.park

ReentrantLock中調(diào)用LockSupport.park代碼如下所示:

 // AbstractQueuedSynchronizer.java
 private final boolean parkAndCheckInterrupt() {
     LockSupport.park(this);
     return Thread.interrupted();
 }

在LockSupport中,void park(Object blocker)實現(xiàn)代碼如下:

 // LockSupport.java
 public static void park(Object blocker) {
     Thread t = Thread.currentThread();
     setBlocker(t, blocker);
     UNSAFE.park(false, 0L);
     setBlocker(t, null);
 }

可以看到在park流程中主要包含以下過程:

獲取當前線程

將傳入的對象設置為該線程的parkBlocker

setBlocker函數(shù)實現(xiàn)如下所示:

 private static void setBlocker(Thread t, Object arg) {
     // Even though volatile, hotspot doesn't need a write barrier here.
     UNSAFE.putObject(t, parkBlockerOffset, arg);
 }

可以看到這里新出現(xiàn)了UNSAFE和parkBlockerOffset兩個標識,這兩個是用來干嘛的?我們一起看看其聲明的代碼:

 private static final sun.misc.Unsafe UNSAFE;
 private static final long parkBlockerOffset;
 static {
     try {
         UNSAFE = sun.misc.Unsafe.getUnsafe();
         Class<?> tk = Thread.class;
         parkBlockerOffset = UNSAFE.objectFieldOffset
             (tk.getDeclaredField("parkBlocker"));
         .....
     } catch (Exception ex) { throw new Error(ex); }
 }

可以看到UNSAFE對象是通過Unsafe.getUnsafe()獲取的,那么Unsafe這個類到底是干嘛的?

大家都知道Java對象在內(nèi)存中創(chuàng)建,大多數(shù)情況下我們都是通過類的對象去修改和訪問內(nèi)存中的數(shù)據(jù)的,那么如果需要直接從內(nèi)存修改某一對象的取值,應該怎么做呢?就是使用Unsafe類,該類只允許在JDK信任的類中調(diào)用(當前也可以用反射實例化該類對象)。

在Unsafe類中定義了兩個重要函數(shù)park和unpark,其中park用于實現(xiàn)線程阻塞,unpark用于實現(xiàn)線程喚醒(Unsafe本質(zhì)上是操作線程的Parker對象來完成線程阻塞和喚醒的,具體見參考鏈接,了解即可),上文中的parkBlockerOffset正是定義了Thread類的parkBlocker屬性成員的內(nèi)存偏移量,使用該值再結合Unsafe對象就可以實現(xiàn)直接操作內(nèi)存中的parkBlocker值的目的,Thread類中的parkBlocker聲明如下:

 // Thread.java
 volatile Object parkBlocker;

可以得到這一環(huán)節(jié)主要是將AQS作為blocker設置到當前線程的parkBlocker成員屬性上。

CAS底層也是通過Unsafe執(zhí)行的

執(zhí)行UNSAFE.park

結合上文可知,這步完成后,當前線程阻塞

設置線程的parkBlocker為null

第三步中線程處于阻塞狀態(tài),當然就不能執(zhí)行設置parkBlocker為null的操作了,那么什么時候執(zhí)行呢?當線程從阻塞狀態(tài)喚醒時,執(zhí)行該步驟,使得線程的parkBlocker對象恢復初始狀態(tài)。

LockSupport.unpark

LockSupport.unpark代碼如下所示:

 // LockSupport.java
 public static void unpark(Thread thread) {
     if (thread != null)
         UNSAFE.unpark(thread);
 }

可以看出當傳入的線程不為空時,執(zhí)行Unsafe的park函數(shù)喚醒當前線程,取消阻塞,此時繼續(xù)執(zhí)行park函數(shù)中的setBlocker(null),將parkBlocker成員設置為null。

參考鏈接  http://www.dbjr.com.cn/article/272073.htm

以上就是java LockSupport實現(xiàn)原理示例解析的詳細內(nèi)容,更多關于java LockSupport原理的資料請關注腳本之家其它相關文章!

相關文章

  • IntelliJ IDEA配置java環(huán)境及解決IDEA不能直接運行單個JAVA文件的問題

    IntelliJ IDEA配置java環(huán)境及解決IDEA不能直接運行單個JAVA文件的問題

    這篇文章主要介紹了IntelliJ IDEA配置java環(huán)境及解決IDEA不能直接運行單個JAVA文件的問題,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • JAVA HashMap詳細介紹和示例

    JAVA HashMap詳細介紹和示例

    我們先對HashMap有個整體認識,然后再學習它的源碼,最后再通過實例來學會使用HashMap。
    2013-11-11
  • idea以任意順序debug多線程程序的具體用法

    idea以任意順序debug多線程程序的具體用法

    在idea中使用debug可以讓多個線程以任意順序執(zhí)行,接下來通過本文給大家介紹idea以任意順序debug多線程程序的具體用法,需要的朋友參考下吧
    2021-08-08
  • 詳解備忘錄模式及其在Java設計模式編程中的實現(xiàn)

    詳解備忘錄模式及其在Java設計模式編程中的實現(xiàn)

    這篇文章主要介紹了詳解備忘錄模式及其在Java設計模式編程中的實現(xiàn),備忘錄模式數(shù)據(jù)的存儲過程中應當注意淺拷貝和深拷貝的問題,需要的朋友可以參考下
    2016-04-04
  • Java代碼注釋規(guī)范(動力節(jié)點整理)

    Java代碼注釋規(guī)范(動力節(jié)點整理)

    代碼注釋是架起程序設計者與程序閱讀者之間的通信橋梁,最大限度的提高團隊開發(fā)合作效率。也是程序代碼可維護性的重要環(huán)節(jié)之一。下面通過本文說一下我們在日常開發(fā)中使用的代碼注釋規(guī)范
    2017-03-03
  • Java讀取Properties文件的七種方法的總結

    Java讀取Properties文件的七種方法的總結

    這篇文章主要介紹了Java讀取Properties文件的七種方法的總結的相關資料,需要的朋友可以參考下
    2017-07-07
  • maven坐標Dependencies和Exclusions的使用

    maven坐標Dependencies和Exclusions的使用

    這篇文章主要介紹了maven坐標Dependencies和Exclusions的使用,很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java8如何通過Lambda處理List集合

    Java8如何通過Lambda處理List集合

    這篇文章主要介紹了java8如何通過Lambda處理List集合,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-01-01
  • Dubbo服務無法注冊到ZK上問題

    Dubbo服務無法注冊到ZK上問題

    這篇文章主要介紹了Dubbo服務無法注冊到ZK上問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Java并發(fā)編程——volatile關鍵字

    Java并發(fā)編程——volatile關鍵字

    這篇文章主要介紹了Java并發(fā)編程——volatile關鍵字的相關資料,幫助大家更好的理解和學習Java并發(fā)編程,感興趣的朋友可以了解下
    2020-10-10

最新評論