国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

首頁(yè) Java java教程 多執(zhí)行緒概念 部分死鎖

多執(zhí)行緒概念 部分死鎖

Nov 05, 2024 am 10:03 AM

歡迎來(lái)到我們的多線程系列的第 3 部分!

  • 在第 1 部分中,我們探討了 原子性不變性。
  • 在第 2 部分中,我們討論了飢餓。

在這一部分中,我們將深入研究多執(zhí)行緒中死鎖的機(jī)制。原因是什麼,如何識(shí)別以及可以使用的預(yù)防策略,以避免將程式碼變成僵局。應(yīng)用程式逐漸停止,通常沒(méi)有任何明顯的錯(cuò)誤,讓開(kāi)發(fā)人員感到困惑,系統(tǒng)凍結(jié)。

Multithreading Concepts Part  Deadlock

探索並發(fā)的複雜軌跡

理解死鎖的一個(gè)有用的類比是想像一個(gè)鐵路網(wǎng)絡(luò),在相交的軌道上有多列火車。

由於每列火車都在等待下一列火車開(kāi)動(dòng),因此沒(méi)有一列火車可以繼續(xù)行駛,從而導(dǎo)致僵局。在這種情況下,低效率的信號(hào)系統(tǒng)讓每趟列車在沒(méi)有先確認(rèn)下一段是否空閒的情況下就進(jìn)入了各自的路段,從而使所有列車陷入了一個(gè)無(wú)法打破的循環(huán)。

這個(gè)火車範(fàn)例說(shuō)明了多線程中的典型死鎖,其中線程(如火車)在等待其他資源被釋放時(shí)保留資源(軌道部分),但沒(méi)有一個(gè)可以前進(jìn)。為了防止這種軟體死鎖,必須實(shí)施有效的資源管理策略(類似於更智慧的鐵路訊號(hào)),以避免循環(huán)依賴並確保每個(gè)執(zhí)行緒的安全通道。

1.什麼是死鎖?

死鎖是執(zhí)行緒(或行程)無(wú)限期阻塞、等待其他執(zhí)行緒持有的資源的情況。這種情況會(huì)導(dǎo)致無(wú)法打破的依賴關(guān)係循環(huán),任何涉及的執(zhí)行緒都無(wú)法取得進(jìn)展。在探索檢測(cè)、預(yù)防和解決方法之前,了解死鎖的基礎(chǔ)知識(shí)至關(guān)重要。

2. 死鎖發(fā)生的條件

要發(fā)生死鎖,必須同時(shí)滿足四個(gè)條件,稱為科夫曼條件:

  • 互斥:至少一個(gè)資源必須以不可共享模式保存,這意味著一次只有一個(gè)執(zhí)行緒可以使用它。

  • 持有並等待:執(zhí)行緒必須持有一種資源,並等待其他執(zhí)行緒持有的其他資源。

  • 無(wú)搶佔(zhàn):無(wú)法從執(zhí)行緒強(qiáng)行奪走資源。他們必須自願(yuàn)釋放。

  • 循環(huán)等待:存在一個(gè)封閉的執(zhí)行緒鏈,其中每個(gè)執(zhí)行緒至少擁有鏈中下一個(gè)執(zhí)行緒所需的一個(gè)資源。

Multithreading Concepts Part  Deadlock

我們用時(shí)序圖來(lái)理解

Multithreading Concepts Part  Deadlock

在上面的動(dòng)畫中,

  • 執(zhí)行緒 A 持有資源 1 並等待資源 2
  • 當(dāng)執(zhí)行緒 B 持有資源 2 並等待資源 1

上面共享的所有四個(gè)死鎖條件都存在,這會(huì)導(dǎo)致無(wú)限期的阻塞。打破其中任何一個(gè)都可以防止僵局。

3. 偵測(cè)/監(jiān)控死鎖

偵測(cè)死鎖,尤其是在大規(guī)模應(yīng)用程式中,可能具有挑戰(zhàn)性。然而,以下方法可以幫助識(shí)別死鎖

  • 工具: Java 的 JConsole、VisualVM 以及 IDE 中的執(zhí)行緒分析器可以即時(shí)偵測(cè)死鎖。
  • 執(zhí)行緒轉(zhuǎn)儲(chǔ)與日誌:分析執(zhí)行緒轉(zhuǎn)儲(chǔ)可以揭示等待執(zhí)行緒及其所持有的資源。

有關(guān)如何調(diào)試/監(jiān)視死鎖的詳細(xì)概述,請(qǐng)?jiān)L問(wèn)使用 VisualVM 和 jstack 調(diào)試和監(jiān)視死鎖

4. 預(yù)防死鎖的策略

  • 應(yīng)用等待死亡和傷口等待方案
    等待死亡方案:當(dāng)一個(gè)執(zhí)行緒請(qǐng)求另一個(gè)執(zhí)行緒持有的鎖時(shí),資料庫(kù)會(huì)評(píng)估相對(duì)優(yōu)先權(quán)(通?;睹總€(gè)執(zhí)行緒的時(shí)間戳記)。如果請(qǐng)求執(zhí)行緒的優(yōu)先權(quán)較高,則等待;否則,它會(huì)死掉(重新啟動(dòng))。
    Wound-Wait 方案:如果請(qǐng)求執(zhí)行緒具有較高優(yōu)先權(quán),它會(huì)透過(guò)強(qiáng)制釋放鎖來(lái)破壞(搶佔(zhàn))較低優(yōu)先權(quán)執(zhí)行緒。

  • 共享狀態(tài)的不可變物件
    盡可能將共享狀態(tài)設(shè)計(jì)為不可變。由於不可變物件無(wú)法修改,因此它們無(wú)需鎖定即可進(jìn)行並發(fā)訪問(wèn),從而降低死鎖風(fēng)險(xiǎn)並簡(jiǎn)化程式碼。

  • 使用具有逾時(shí)的 tryLock 來(lái)取得鎖定:與標(biāo)準(zhǔn)同步區(qū)塊不同,ReentrantLock 允許使用 tryLock(timeout, unit) 在指定時(shí)間內(nèi)嘗試取得鎖定。如果在此時(shí)間內(nèi)未取得鎖,它將釋放資源,防止無(wú)限期阻塞。

ReentrantLock lock1 = new ReentrantLock();
ReentrantLock lock2 = new ReentrantLock();

public void acquireLocks() {
    try {
        if (lock1.tryLock(100, TimeUnit.MILLISECONDS)) {
            try {
                if (lock2.tryLock(100, TimeUnit.MILLISECONDS)) {
                    // Critical section
                }
            } finally {
                lock2.unlock();
            }
        }
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    } finally {
        lock1.unlock();
    }
}

  • 鎖定排序與釋放 為鎖獲取設(shè)定嚴(yán)格的全域順序。如果所有執(zhí)行緒以一致的順序取得鎖,則不太可能形成循環(huán)依賴,從而避免死鎖。例如,在整個(gè)程式碼庫(kù)中始終先取得 lock1,然後再取得 lock2。這種做法在較大的應(yīng)用程式中可能具有挑戰(zhàn)性,但對(duì)於降低死鎖風(fēng)險(xiǎn)非常有效。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockOrderingExample {

    private static final Lock lock1 = new ReentrantLock();
    private static final Lock lock2 = new ReentrantLock();

    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            acquireLocksInOrder(lock1, lock2);
        });

        Thread thread2 = new Thread(() -> {
            acquireLocksInOrder(lock1, lock2);
        });

        thread1.start();
        thread2.start();
    }

    private static void acquireLocksInOrder(Lock firstLock, Lock secondLock) {
        try {
            firstLock.lock();
            System.out.println(Thread.currentThread().getName() + " acquired lock1");

            secondLock.lock();
            System.out.println(Thread.currentThread().getName() + " acquired lock2");

            // Perform some operations

        } finally {
            secondLock.unlock();
            System.out.println(Thread.currentThread().getName() + " released lock2");

            firstLock.unlock();
            System.out.println(Thread.currentThread().getName() + " released lock1");
        }
    }
}
  • 使用線程安全/並發(fā)集合:Java 的java.util.concurrent 套件提供了常見(jiàn)資料結(jié)構(gòu)(ConcurrentHashMap、CopyOnWriteArrayList 等)的線程安全實(shí)現(xiàn),可以在內(nèi)部處理同步,減少需要顯式鎖。這些集合最大限度地減少了死鎖,因?yàn)樗鼈冎荚谑褂脙?nèi)部分區(qū)等技術(shù)來(lái)避免明確鎖定的需要。

  • 避免巢狀鎖
    盡量減少在同一塊內(nèi)取得多個(gè)鎖以避免循環(huán)依賴。如果需要嵌套鎖,請(qǐng)使用一致的鎖定順序

軟體工程師的要點(diǎn)

  • 每當(dāng)您建立需要鎖定的設(shè)計(jì)時(shí),就有可能出現(xiàn)死鎖。
  • 死鎖是由進(jìn)程之間的依賴關(guān)係循環(huán)引起的阻塞問(wèn)題。沒(méi)有任何行程可以取得進(jìn)展,因?yàn)槊總€(gè)行程都在等待另一個(gè)行程持有的資源,而且沒(méi)有一個(gè)行程可以繼續(xù)釋放資源。
  • 死鎖更為嚴(yán)重,因?yàn)樗鼤?huì)完全停止所涉及的進(jìn)程,並且需要打破死鎖循環(huán)才能恢復(fù)。
  • 死鎖只有當(dāng)有兩個(gè)不同的鎖時(shí)才會(huì)發(fā)生,即當(dāng)您持有一個(gè)鎖並等待另一個(gè)鎖釋放時(shí)。 (但是,死鎖還有更多條件)。
  • 線程安全並不意味著無(wú)死鎖。它僅保證程式碼將根據(jù)其介面進(jìn)行操作,即使是從多個(gè)執(zhí)行緒呼叫時(shí)也是如此。使類別線程安全通常包括添加鎖以確保安全執(zhí)行。

尾奏

無(wú)論您是初學(xué)者還是經(jīng)驗(yàn)豐富的開(kāi)發(fā)人員,了解死鎖對(duì)於在並發(fā)系統(tǒng)中編寫健全、高效的程式碼至關(guān)重要。在本文中,我們探討了死鎖是什麼、原因以及預(yù)防死鎖的實(shí)用方法。透過(guò)實(shí)施有效的資源分配策略、分析任務(wù)依賴性以及利用線程轉(zhuǎn)儲(chǔ)和死鎖檢測(cè)工具等工具,開(kāi)發(fā)人員可以最大限度地降低死鎖風(fēng)險(xiǎn)並優(yōu)化程式碼以實(shí)現(xiàn)平滑的並發(fā)。

當(dāng)我們繼續(xù)了解多執(zhí)行緒的核心概念時(shí),請(qǐng)繼續(xù)關(guān)注本系列的下一篇文章。我們將深入關(guān)鍵部分,了解如何在多個(gè)執(zhí)行緒之間安全地管理共享資源。我們也將討論競(jìng)爭(zhēng)條件的概念,這是一種常見(jiàn)的並發(fā)問(wèn)題,如果不加以控制,可能會(huì)導(dǎo)致不可預(yù)測(cè)的行為和錯(cuò)誤。

透過(guò)每一步,您都會(huì)更深入地了解如何使您的應(yīng)用程式執(zhí)行緒安全、高效且具有彈性。不斷突破多執(zhí)行緒知識(shí)的界限,建立更好、效能更高的軟體!

參考

  • Stackoverflow
  • 資訊圖表
  • 如何偵測(cè)並修復(fù)死鎖

以上是多執(zhí)行緒概念 部分死鎖的詳細(xì)內(nèi)容。更多資訊請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願(yuàn)投稿,版權(quán)歸原作者所有。本站不承擔(dān)相應(yīng)的法律責(zé)任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請(qǐng)聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動(dòng)的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強(qiáng)大的PHP整合開(kāi)發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺(jué)化網(wǎng)頁(yè)開(kāi)發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)程式碼編輯軟體(SublimeText3)

為什麼我們需要包裝紙課? 為什麼我們需要包裝紙課? Jun 28, 2025 am 01:01 AM

Java使用包裝類是因?yàn)榛緮?shù)據(jù)類型無(wú)法直接參與面向?qū)ο癫僮?,而?shí)際需求中常需對(duì)象形式;1.集合類只能存儲(chǔ)對(duì)象,如List利用自動(dòng)裝箱存儲(chǔ)數(shù)值;2.泛型不支持基本類型,必須使用包裝類作為類型參數(shù);3.包裝類可表示null值,用於區(qū)分未設(shè)置或缺失的數(shù)據(jù);4.包裝類提供字符串轉(zhuǎn)換等實(shí)用方法,便於數(shù)據(jù)解析與處理,因此在需要這些特性的場(chǎng)景下,包裝類不可或缺。

hashmap和hashtable之間的區(qū)別? hashmap和hashtable之間的區(qū)別? Jun 24, 2025 pm 09:41 PM

HashMap與Hashtable的區(qū)別主要體現(xiàn)在線程安全、null值支持及性能方面。 1.線程安全方面,Hashtable是線程安全的,其方法大多為同步方法,而HashMap不做同步處理,非線程安全;2.null值支持上,HashMap允許一個(gè)null鍵和多個(gè)null值,Hashtable則不允許null鍵或值,否則拋出NullPointerException;3.性能方面,HashMap因無(wú)同步機(jī)制效率更高,Hashtable因每次操作加鎖性能較低,推薦使用ConcurrentHashMap替

JIT編譯器如何優(yōu)化代碼? JIT編譯器如何優(yōu)化代碼? Jun 24, 2025 pm 10:45 PM

JIT編譯器通過(guò)方法內(nèi)聯(lián)、熱點(diǎn)檢測(cè)與編譯、類型推測(cè)與去虛擬化、冗餘操作消除四種方式優(yōu)化代碼。 1.方法內(nèi)聯(lián)減少調(diào)用開(kāi)銷,將頻繁調(diào)用的小方法直接插入調(diào)用處;2.熱點(diǎn)檢測(cè)識(shí)別高頻執(zhí)行代碼並集中優(yōu)化,節(jié)省資源;3.類型推測(cè)收集運(yùn)行時(shí)類型信息實(shí)現(xiàn)去虛擬化調(diào)用,提升效率;4.冗餘操作消除根據(jù)運(yùn)行數(shù)據(jù)刪除無(wú)用計(jì)算和檢查,增強(qiáng)性能。

什麼是接口中的靜態(tài)方法? 什麼是接口中的靜態(tài)方法? Jun 24, 2025 pm 10:57 PM

StaticmethodsininterfaceswereintroducedinJava8toallowutilityfunctionswithintheinterfaceitself.BeforeJava8,suchfunctionsrequiredseparatehelperclasses,leadingtodisorganizedcode.Now,staticmethodsprovidethreekeybenefits:1)theyenableutilitymethodsdirectly

什麼是實(shí)例初始器塊? 什麼是實(shí)例初始器塊? Jun 25, 2025 pm 12:21 PM

實(shí)例初始化塊在Java中用於在創(chuàng)建對(duì)象時(shí)運(yùn)行初始化邏輯,其執(zhí)行先於構(gòu)造函數(shù)。它適用於多個(gè)構(gòu)造函數(shù)共享初始化代碼、複雜字段初始化或匿名類初始化場(chǎng)景,與靜態(tài)初始化塊不同的是它每次實(shí)例化時(shí)都會(huì)執(zhí)行,而靜態(tài)初始化塊僅在類加載時(shí)運(yùn)行一次。

變量的最終關(guān)鍵字是什麼? 變量的最終關(guān)鍵字是什麼? Jun 24, 2025 pm 07:29 PM

InJava,thefinalkeywordpreventsavariable’svaluefrombeingchangedafterassignment,butitsbehaviordiffersforprimitivesandobjectreferences.Forprimitivevariables,finalmakesthevalueconstant,asinfinalintMAX_SPEED=100;wherereassignmentcausesanerror.Forobjectref

什麼是類型鑄造? 什麼是類型鑄造? Jun 24, 2025 pm 11:09 PM

類型轉(zhuǎn)換有兩種:隱式和顯式。 1.隱式轉(zhuǎn)換自動(dòng)發(fā)生,如將int轉(zhuǎn)為double;2.顯式轉(zhuǎn)換需手動(dòng)操作,如使用(int)myDouble。需要類型轉(zhuǎn)換的情況包括處理用戶輸入、數(shù)學(xué)運(yùn)算或函數(shù)間傳遞不同類型的值時(shí)。需要注意的問(wèn)題有:浮點(diǎn)數(shù)轉(zhuǎn)整數(shù)會(huì)截?cái)嘈?shù)部分、大類型轉(zhuǎn)小類型可能導(dǎo)致數(shù)據(jù)丟失、某些語(yǔ)言不允許直接轉(zhuǎn)換特定類型。正確理解語(yǔ)言的轉(zhuǎn)換規(guī)則有助於避免錯(cuò)誤。

什麼是工廠模式? 什麼是工廠模式? Jun 24, 2025 pm 11:29 PM

工廠模式用於封裝對(duì)象創(chuàng)建邏輯,使代碼更靈活、易維護(hù)、松耦合。其核心答案是:通過(guò)集中管理對(duì)象創(chuàng)建邏輯,隱藏實(shí)現(xiàn)細(xì)節(jié),支持多種相關(guān)對(duì)象的創(chuàng)建。具體描述如下:工廠模式將對(duì)象創(chuàng)建交給專門的工廠類或方法處理,避免直接使用newClass();適用於多類型相關(guān)對(duì)象創(chuàng)建、創(chuàng)建邏輯可能變化、需隱藏實(shí)現(xiàn)細(xì)節(jié)的場(chǎng)景;例如支付處理器中通過(guò)工廠統(tǒng)一創(chuàng)建Stripe、PayPal等實(shí)例;其實(shí)現(xiàn)包括工廠類根據(jù)輸入?yún)?shù)決定返回的對(duì)象,所有對(duì)象實(shí)現(xiàn)共同接口;常見(jiàn)變體有簡(jiǎn)單工廠、工廠方法和抽象工廠,分別適用於不同複雜度的需求。

See all articles