最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

多線程-lock與lockInterruptibly的區(qū)別及說明

 更新時間:2025年02月27日 10:08:44   作者:九轉(zhuǎn)成圣  
文章主要討論了Java中ReentrantLock的lock和lockInterruptibly方法的區(qū)別,以及AQS中的雙向鏈表設(shè)計,lock方法不響應(yīng)中斷,而lockInterruptibly方法會響應(yīng)中斷,AQS的雙向鏈表設(shè)計使得線程管理更加高效和靈活,適用于高并發(fā)場景

多線程lock與lockInterruptibly區(qū)別

在多線程編程中,鎖(Lock)是用來確保多個線程在訪問共享資源時能夠保持一致性和正確性的關(guān)鍵工具。

Java 提供了多種實現(xiàn)鎖的機制,其中最常用的是 ReentrantLock。ReentrantLock 提供了兩種獲取鎖的方法:locklockInterruptibly。

這兩者在處理線程中斷時表現(xiàn)不同,理解這些差異對于編寫健壯的多線程程序至關(guān)重要。

lock 方法

示例代碼:

public static void lock() {
    Lock lock = new ReentrantLock();
    try {
        lock.lock();
        Thread t1 = new Thread(() -> {
            Thread currentThread = Thread.currentThread();
            try {
                lock.lock();
                System.out.println(currentThread.getName() + " lock后的代碼");
            } finally {
                lock.unlock();
            }
            System.out.println("currentThread = " + currentThread.getName() + " isInterrupted:" + currentThread.isInterrupted());
        }, "t1");
        t1.start();
        t1.interrupt();
        System.out.println("currentThread = " + Thread.currentThread().getName());
    } finally {
        lock.unlock();
    }
}

執(zhí)行結(jié)果:

currentThread = main
t1 lock后的代碼
currentThread = t1 isInterrupted:true

解釋:

在這個示例中,主線程(main)首先獲取了鎖。然后啟動一個新線程(t1),該線程嘗試再次獲取同一個鎖。主線程在啟動 t1 后立即調(diào)用 t1.interrupt() 方法中斷 t1 線程。

盡管 t1 線程被中斷,它還是成功獲取到了鎖并執(zhí)行了鎖后的代碼。這是因為 lock 方法在獲取鎖時不會理會線程的中斷狀態(tài),只要鎖可用,它就會獲取鎖。換句話說,即使線程被中斷,它也會繼續(xù)等待獲取鎖,直到成功為止。

lockInterruptibly 方法

示例代碼:

public static void lockInterruptiblyDemo() {
    Lock lock = new ReentrantLock();
    try {
        lock.lock();
        Thread t1 = new Thread(() -> {
            Thread currentThread = Thread.currentThread();
            try {
                lock.lockInterruptibly();
                System.out.println(currentThread.getName() + " lockInterruptibly后的代碼");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
            System.out.println("currentThread = " + currentThread.getName() + " isInterrupted:" + currentThread.isInterrupted());
        }, "t1");
        t1.start();
        t1.interrupt();
        System.out.println("currentThread = " + Thread.currentThread().getName());
    } finally {
        lock.unlock();
    }
}

執(zhí)行結(jié)果:

currentThread = main
java.lang.InterruptedException
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1220)
    at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
    at Xxx.lambda$lockInterruptiblyDemo$1(Xxx.java:39)
    at java.lang.Thread.run(Thread.java:748)
Exception in thread "t1" java.lang.IllegalMonitorStateException
    at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
    at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
    at Xxx.lambda$lockInterruptiblyDemo$1(Xxx.java:44)
    at java.lang.Thread.run(Thread.java:748)

解釋:

在這個示例中,t1 線程嘗試獲取鎖時調(diào)用了 lockInterruptibly 方法。與 lock 方法不同,lockInterruptibly 在嘗試獲取鎖時會檢查線程的中斷狀態(tài)。如果線程被中斷,它會立即拋出 InterruptedException 異常,而不會繼續(xù)等待獲取鎖。

執(zhí)行結(jié)果顯示,t1 線程在嘗試獲取鎖時被中斷,并且拋出了 InterruptedException。由于異常被捕獲并打印,t1 線程并沒有獲取鎖,這避免了在某些情況下可能出現(xiàn)的死鎖問題。

區(qū)別總結(jié)

中斷響應(yīng)

  • lock 方法:不響應(yīng)中斷,線程會一直嘗試獲取鎖,直到成功為止。
  • lockInterruptibly 方法:響應(yīng)中斷,線程在檢測到中斷后會拋出 InterruptedException 并停止嘗試獲取鎖。

使用場景

  • lock 方法適用于不需要考慮中斷的場景。
  • lockInterruptibly 方法適用于需要及時響應(yīng)中斷的場景,例如當需要能夠中斷線程來避免死鎖時。

面試題:為什么 AQS 中的隊列設(shè)計為雙向鏈表?

AQS(AbstractQueuedSynchronizer)是 Java 并發(fā)包中鎖和同步器的基礎(chǔ)框架。AQS 內(nèi)部使用了一個 FIFO(先進先出)的雙向鏈表來管理等待線程的隊列。

原因:

雙向遍歷

  • 當一個節(jié)點(線程)被喚醒時,需要能方便地找到前驅(qū)節(jié)點以確保線程的喚醒順序和正確性。
  • 雙向鏈表允許從當前節(jié)點輕松訪問前驅(qū)節(jié)點,從而能夠修改前驅(qū)節(jié)點的狀態(tài)。

節(jié)點刪除

  • 在一些情況下,節(jié)點(線程)可能需要從隊列中取消。
  • 雙向鏈表使得刪除節(jié)點操作更加高效,因為可以直接通過前驅(qū)和后繼節(jié)點來重新鏈接,而不需要從頭遍歷。

狀態(tài)更新

  • 雙向鏈表結(jié)構(gòu)使得更新節(jié)點狀態(tài)(如將節(jié)點從等待狀態(tài)變?yōu)檫\行狀態(tài))更為便捷
  • 可以在節(jié)點之間高效地傳播狀態(tài)信息

實現(xiàn)復(fù)雜性

  • 雖然雙向鏈表在實現(xiàn)上稍微復(fù)雜一些
  • 但提供的靈活性和操作效率的提升在高并發(fā)場景中是值得的

通過這種設(shè)計,AQS 能夠更高效地管理線程隊列,確保鎖和同步器的高性能和正確性。

詳細分析:AQS 中的雙向鏈表

AQS 是一個基于節(jié)點的框架,所有等待獲取鎖的線程都會被封裝成一個節(jié)點并加入到等待隊列中。該隊列的結(jié)構(gòu)和操作直接影響鎖的性能和響應(yīng)能力。

AQS 中的主要節(jié)點結(jié)構(gòu):

每個節(jié)點包含以下主要部分:

  • 前驅(qū)節(jié)點:指向前一個等待線程的節(jié)點。
  • 后繼節(jié)點:指向后一個等待線程的節(jié)點。
  • 線程引用:包含正在等待獲取鎖的線程的引用。
  • 狀態(tài):表示線程的等待狀態(tài)(如等待、取消等)。

操作示例:

入隊

  • 當一個線程請求獲取鎖但鎖不可用時,它會被封裝成一個節(jié)點并加入到隊列末尾。
  • 雙向鏈表結(jié)構(gòu)允許快速定位隊尾并將新節(jié)點鏈接上去。

出隊

  • 當一個節(jié)點被喚醒時(通常是獲取到鎖),它需要從隊列中移除。
  • 雙向鏈表結(jié)構(gòu)允許通過前驅(qū)和后繼節(jié)點高效地重新鏈接,刪除節(jié)點。

狀態(tài)傳播

  • 當一個節(jié)點狀態(tài)改變時(如從等待到運行),它需要通知前驅(qū)或后繼節(jié)點。
  • 雙向鏈表允許在節(jié)點之間高效地傳播狀態(tài),確保隊列中的每個線程都能正確響應(yīng)狀態(tài)變化。

總結(jié)

理解 locklockInterruptibly 的區(qū)別有助于我們在多線程編程中選擇適當?shù)逆i獲取方式,確保程序的健壯性和響應(yīng)能力。而 AQS 中的雙向鏈表設(shè)計則是確保鎖和同步器高效管理等待線程隊列的重要基礎(chǔ),這種設(shè)計使得線程管理更加高效和靈活,在高并發(fā)場景中表現(xiàn)尤為突出。通過深入理解這些底層機制,我們可以更好地編寫高性能的多線程應(yīng)用程序。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java使用HttpClient詳細示例

    Java使用HttpClient詳細示例

    這篇文章介紹了Java使用HttpClient的詳細示例,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-12-12
  • Java中Calendar類的一些常用方法小結(jié)

    Java中Calendar類的一些常用方法小結(jié)

    項目當中,我們經(jīng)常會涉及到對時間的處理,Date類最主要的作用就是獲得當前時間,同時這個類里面也具有設(shè)置時間以及一些其他的功能,但更推薦使用 Calendar 類進行時間和日期的處理,這篇文章主要給大家介紹了關(guān)于Java中Calendar類的一些常用方法,需要的朋友可以參考下
    2021-11-11
  • java中httpclient封裝post請求和get的請求實例

    java中httpclient封裝post請求和get的請求實例

    這篇文章主要介紹了java中httpclient封裝post請求和get的請求實例,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • IDEA中配置Python環(huán)境并運行方式

    IDEA中配置Python環(huán)境并運行方式

    本文介紹了在Mac和Windows平臺上安裝Python環(huán)境的方法,并詳細講解了如何在IntelliJ IDEA中安裝Python插件、創(chuàng)建Python工程和運行Python文件,同時,還提到了一些常用的Python框架,如Django、Google App Engine和SQL支持
    2025-03-03
  • java之Objects.nonNull用法代碼解讀

    java之Objects.nonNull用法代碼解讀

    這篇文章主要介紹了java之Objects.nonNull用法代碼,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • Java語言實現(xiàn)簡單FTP軟件 FTP本地文件管理模塊實現(xiàn)(9)

    Java語言實現(xiàn)簡單FTP軟件 FTP本地文件管理模塊實現(xiàn)(9)

    這篇文章主要為大家詳細介紹了Java語言實現(xiàn)簡單FTP軟件,F(xiàn)TP本地文件管理模塊的實現(xiàn)方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • idea中創(chuàng)建新類時自動添加注釋的實現(xiàn)

    idea中創(chuàng)建新類時自動添加注釋的實現(xiàn)

    在每次使用idea創(chuàng)建一個新類時,過了一段時間發(fā)現(xiàn)看不懂這個類是用來干嘛的,為了解決這個問題,我們可以設(shè)置在創(chuàng)建一個新類時自動添加注釋,幫助我們理解這個類的用處,本文主要介紹了在idea中創(chuàng)建新類時自動添加注釋的實現(xiàn),感興趣的可以了解一下
    2025-03-03
  • Java系統(tǒng)升級與遷移的完整指南

    Java系統(tǒng)升級與遷移的完整指南

    在Java生態(tài)中,系統(tǒng)升級和遷移是開發(fā)者必須面對的“成人禮”,從JAR地獄到模塊化戰(zhàn)爭,從Java 8到Java 17的版本跳躍,每一次升級都伴隨著技術(shù)債的清算、架構(gòu)的重構(gòu)和性能的飛躍,所以本文給大家介紹了Java系統(tǒng)升級與遷移的完整指南,需要的朋友可以參考下
    2025-08-08
  • Spring Boot Gateway 從入門到精通全面指南

    Spring Boot Gateway 從入門到精通全面指南

    Spring Cloud Gateway 作為微服務(wù)架構(gòu)中的重要組件,提供了強大而靈活的路由與過濾功能,通過本教程,您應(yīng)該已經(jīng)了解了如何集成 Spring Cloud Gateway、如何配置路由規(guī)則以及如何利用其豐富的功能來滿足各種業(yè)務(wù)需求,感興趣的朋友跟隨小編一起看看吧
    2025-09-09
  • SpringBoot基于數(shù)據(jù)庫實現(xiàn)定時任務(wù)過程解析

    SpringBoot基于數(shù)據(jù)庫實現(xiàn)定時任務(wù)過程解析

    這篇文章主要介紹了SpringBoot基于數(shù)據(jù)庫實現(xiàn)定時任務(wù)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-12-12

最新評論

台南县| 监利县| 红原县| 涞水县| 闸北区| 丰城市| 德兴市| 康保县| 吉木乃县| 招远市| 宜章县| 兰考县| 奉新县| 渝中区| 蕉岭县| 淮阳县| 彩票| 崇阳县| 富顺县| 分宜县| 阿城市| 凤城市| 安顺市| 福鼎市| 江城| 湟源县| 江口县| 麻阳| 六安市| 灵宝市| 咸阳市| 隆德县| 桂阳县| 抚宁县| 彩票| 巴林左旗| 湖北省| 赤峰市| 都兰县| 营口市| 定襄县|