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

ReentrantLock獲取鎖釋放鎖的流程示例分析

 更新時間:2022年11月23日 16:40:40   作者:Alan_YYL  
這篇文章主要為大家介紹了ReentrantLock獲取鎖釋放鎖的流程示例分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

目的

  • 了解ReentrantLock獲取鎖、釋放鎖的流程

代碼

package com.company.aqs;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 * ReentrantLock使用案例——使用ReentrantLock加鎖
 * @Author: Alan
 * @Date: 2022/11/20 01:38
 */
public class ReentrantLockDemo {
    private static int sum=0;
    private static Lock lock=new ReentrantLock();
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 3; i++) {
            new Thread(()->{
                // 獲取鎖
                lock.lock();
                try {
                    for (int j = 0; j < 1000; j++) {
                        sum++;
                    }
                }finally {
                    // 在finally代碼塊中釋放鎖
                    lock.unlock();
                }
            }).start();
        }
        // 保證所有線程執(zhí)行完畢
        Thread.sleep(1000);
        System.out.println(sum);
    }
}

這是一個使用ReentrantLock實現(xiàn)多線程求和的案例。代碼邏輯比較簡單,外層循環(huán)開啟了3個線程,然后每個線程內(nèi)多sum累加1000,最后輸出結(jié)果sum=1000。

獲取鎖流程

整個過程概括起來就做了兩件事兒

  • 獲取鎖成功,執(zhí)行當前線程內(nèi)的其他事情;
  • 獲取鎖失敗,當前線程加入同步隊列,同時阻塞當前線程。

當?shù)谝粋€線程(thead0)進來的時候,通過CAS去修改state屬性為1,如果成功,通過setExclusiveOwnerThread()方法設(shè)置exclusiveOwnerThread為當前線程

此時,第二個線程(thead1)進來,再去通過CAS修改state屬性為1時,便會失敗,此時進入acquire()方法。最終會走到如下方法,首先通過tryAcquire()方法再次嘗試去獲取鎖。

tryAcquire()方法內(nèi)部還是會通過CAS去獲取鎖。此時鎖資源還被第二線程持有,因此會返回false?,F(xiàn)在接著看acquire()方法中的if判斷。

此時,會進行acquireQueued(addWaiter(Node.EXCLUSIVE), arg))判斷。這里需要執(zhí)行兩個方法addWaiter()和acquireQueued()。首先看addWaiter()方法。這個方法,我們需要關(guān)注以下四點。

  • 首先會先構(gòu)造一個node節(jié)點(節(jié)點內(nèi)部細節(jié),可以看其構(gòu)造方法)。
  • 如果tail(同步隊列尾節(jié)點指針)不為空,其實也就是同步隊列不為空,那么就把第1步構(gòu)建的節(jié)點通過尾插法加入隊列中,然后返回

如果同步隊列為空了,那么執(zhí)行enq()方法,這個方法為我們做了兩件事兒。

  • 如果同步隊列為空,那么初始化隊列
  • 隊列初始化完成后,將node節(jié)點入隊。

通過addWaiter()方法和enq()方法,我們也可以看出來,AQS中的同步隊列是通過雙向鏈表來實現(xiàn)的,節(jié)點入隊和出隊,需要修改兩個指針才行(prev和next)。

addWaiter()方法執(zhí)行執(zhí)行完畢后,我們通過下面這張圖大致看下此時同步隊列中的節(jié)點指向情況。此處,不太理解可以再回頭看看enq()方法的執(zhí)行流程。

addWaiter()方法執(zhí)行執(zhí)行完畢后,會返回入隊后的新節(jié)點。然后開始執(zhí)行acquireQueued()方法。這個方法做了五件事兒。

  • 獲取當前節(jié)點的前驅(qū)節(jié)點p
  • 如果p是頭節(jié)點,那么再次嘗試去獲取鎖,獲取鎖成功,就可以跳出循環(huán)
  • 獲取鎖失敗,通過shouldParkAfterFailedAcquire()去修改waitSatus為-1(為什么修改為-1,這里可以從AQS的源碼中找到原因,后續(xù)獲取鎖的流程也會遵從這個邏輯)

4. parkAndCheckInterrupt()方法會阻塞當前線程,同時,能夠返回當前線程的中斷狀態(tài)(Thread.interrupted()會清除中斷標記位)。

經(jīng)過上述的一通操作,我們可以知道,線程1沒有獲取到鎖,被加入到了同步隊列,并且還對其進行了阻塞。概括下就是四個字“入隊”、“阻塞”。此時我們的同步隊列也變成如下所示。和上述執(zhí)行完addWaiter()方法相比,只是線程1節(jié)點的前驅(qū)節(jié)點,waitStaus被設(shè)置成了-1。

釋放鎖流程

整個過程(只考慮釋放鎖成功)概括起來做了三件事兒

  • 釋放鎖資源;
  • 喚醒同步隊列中頭節(jié)點的后一個節(jié)點對應(yīng)的線程
  • 步驟2被喚醒的該線程嘗試競爭鎖,競爭鎖成功,那么更新同步隊列(即頭節(jié)點出隊)。

當?shù)谝粋€線程(thread0)執(zhí)行完自己的業(yè)務(wù)流程后,就會釋放鎖。此時,我們來看看釋放鎖的流程又是什么樣子的。調(diào)用unlock()方法可以對鎖進行釋放,需要注意的時,為了避免死鎖,需要將該方法的調(diào)用放在fiaally代碼塊中。

當thread0去釋放鎖時,會調(diào)用release()方法,該方法主要做了兩件事兒。

  • 調(diào)用tryRelease()方法釋放鎖

其方法內(nèi)部,會將state設(shè)置為0,同時通過setExclusiveOwnerThread()方法設(shè)置exclusiveOwnerThread為當null,代表此時鎖資源被釋放,沒有任何線程持有鎖資源

如果第一步返回true,即釋放鎖成功,那么開始第二步。第二步首先獲取同步隊列的頭節(jié)點,查看其waitStatus屬性。這里我們把剛才獲取鎖過后,同步隊列中的節(jié)點情況再放一下。此時,我們的head節(jié)點的waitStatus為-1,因此會進入unparkSuccessor()方法

unparkSuccessor()方法,主要做了以下三件事兒。注意第三步,根據(jù)我們當前同步隊列的情況來看,LockSupport.unpark()方法會喚醒線程1。

當執(zhí)行完unparkSuccessor()方法中的LockSupport.unpark()方法后,線程1(thread1)就會被喚醒了。線程1被喚醒過后,我們又來看看線程1的執(zhí)行情況。此時線程1,會繼續(xù)執(zhí)行acquireQueued()方法中的for循環(huán)(注意:這是一個死循環(huán)哦)。執(zhí)行順序和獲取鎖時是一致的,和獲取鎖有所不同的時,此時執(zhí)行第2步獲取鎖是會成功的(因為thread0已經(jīng)釋放鎖了)。

獲取鎖成功后呢,會讓當前同步隊列中的頭節(jié)點出隊,此時,同步隊列中的節(jié)點情況如下所示。

此時,釋放鎖的邏輯就執(zhí)行完成了。歸納起來其實也很簡單,首先釋放鎖資源,然后再喚醒同步隊列中頭節(jié)點的后一個節(jié)點對應(yīng)的線程,最后,更新同步隊列(出隊)。

總結(jié)

以上便是ReentrantLock獲取鎖、釋放鎖的的大致流程。通過這篇文章,讀者對ReentrantLock的獲取鎖、釋放鎖過程有一個大致的了解了,細心的讀者可能會發(fā)現(xiàn),獲取鎖時acquireQueued()方法中有一個隊cancelAcquire()方法的調(diào)用邏輯,這里沒有詳細解釋,博主會在后面的文章中詳細來解釋這個方法的處理邏輯(flag先立下!?。。?。

以上就是ReentrantLock獲取鎖釋放鎖的流程示例分析的詳細內(nèi)容,更多關(guān)于ReentrantLock獲取鎖釋放鎖的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Maven分模塊開發(fā)執(zhí)行指令失敗的問題

    Maven分模塊開發(fā)執(zhí)行指令失敗的問題

    Maven分模塊開發(fā),行指令失敗,modules.module[3]‘ specifies duplicate child module maven_dao @ line 29, column 1的問題,本文給大家分享解決方法,感興趣的朋友跟隨小編一起看看吧
    2020-09-09
  • java.security.egd?作用詳解

    java.security.egd?作用詳解

    這篇文章主要為大家介紹了java.security.egd作用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • 在Java開發(fā)中無法繞開的SpringBoot框架詳解

    在Java開發(fā)中無法繞開的SpringBoot框架詳解

    SpringBoot是一個基于Spring框架的快速開發(fā)框架,它的出現(xiàn)極大地簡化了Spring應(yīng)用的開發(fā)流程,SpringBoot是一個快速開發(fā)的框架,它提供了一種快速構(gòu)建應(yīng)用程序的方式,本文給大家介紹在Java開發(fā)中無法繞開的框架:SpringBoot,感興趣的朋友一起看看吧
    2023-09-09
  • Java使用Optional實現(xiàn)優(yōu)雅避免空指針異常

    Java使用Optional實現(xiàn)優(yōu)雅避免空指針異常

    空指針異常(NullPointerException)可以說是Java程序員最容易遇到的問題了。為了解決這個問題,Java?8?版本中推出了?Optional?類,本文就來講講如何使用Optional實現(xiàn)優(yōu)雅避免空指針異常吧
    2023-03-03
  • 劍指Offer之Java算法習(xí)題精講二叉樹的構(gòu)造和遍歷

    劍指Offer之Java算法習(xí)題精講二叉樹的構(gòu)造和遍歷

    跟著思路走,之后從簡單題入手,反復(fù)去看,做過之后可能會忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會發(fā)現(xiàn)質(zhì)的變化
    2022-03-03
  • 在netty中使用native傳輸協(xié)議的方法

    在netty中使用native傳輸協(xié)議的方法

    這篇文章主要介紹了在netty中使用native傳輸協(xié)議,這里我們只以Kqueue為例介紹了netty中native傳輸協(xié)議的使用,需要的朋友可以參考下
    2022-05-05
  • Java經(jīng)緯度小數(shù)與度分秒相互轉(zhuǎn)換工具類示例詳解

    Java經(jīng)緯度小數(shù)與度分秒相互轉(zhuǎn)換工具類示例詳解

    這篇文章主要介紹了Java經(jīng)緯度小數(shù)與度分秒相互轉(zhuǎn)換工具類,本文通過示例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • SpringBoot Admin健康檢查功能的實現(xiàn)

    SpringBoot Admin健康檢查功能的實現(xiàn)

    admin主要就是告訴運維人員,服務(wù)出現(xiàn)異常,然后進行通知(微信、郵件、短信、釘釘?shù)龋┛梢苑浅?焖偻ㄖ竭\維人員,相當報警功能,接下來通過本文給大家介紹SpringBoot Admin健康檢查的相關(guān)知識,一起看看吧
    2021-06-06
  • Springboot hibernate envers使用過程詳解

    Springboot hibernate envers使用過程詳解

    這篇文章主要介紹了Springboot hibernate envers使用過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-06-06
  • Mybatis update數(shù)據(jù)庫死鎖之獲取數(shù)據(jù)庫連接池等待

    Mybatis update數(shù)據(jù)庫死鎖之獲取數(shù)據(jù)庫連接池等待

    這篇文章主要介紹了Mybatis update數(shù)據(jù)庫死鎖之獲取數(shù)據(jù)庫連接池等待的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-07-07

最新評論