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

Java中的線程死鎖是什么?如何避免?

 更新時間:2020年09月08日 14:32:50   作者:崔笑顏  
這篇文章主要介紹了Java中線程死鎖的相關資料,以及避免死鎖的方法,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下

認識線程死鎖

多個線程同時被阻塞,它們中的一個或者全部都在等待某個資源被釋放。由于線程被無限期地阻塞,因此程序不可能正常終止。

如下圖所示,線程 A 持有資源 2,線程 B 持有資源 1,他們同時都想申請對方的資源,所以這兩個線程就會互相等待而進入死鎖狀態(tài)。

下面通過一個例子來說明線程死鎖,代碼模擬了上圖的死鎖的情況 (代碼來源于《并發(fā)編程之美》):

public class DeadLockDemo {
 private static Object resource1 = new Object();//資源 1
 private static Object resource2 = new Object();//資源 2

 public static void main(String[] args) {
  new Thread(() -> {
   synchronized (resource1) {
    System.out.println(Thread.currentThread() + "get resource1");
    try {
     Thread.sleep(1000);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    System.out.println(Thread.currentThread() + "waiting get resource2");
    synchronized (resource2) {
     System.out.println(Thread.currentThread() + "get resource2");
    }
   }
  }, "線程 1").start();

  new Thread(() -> {
   synchronized (resource2) {
    System.out.println(Thread.currentThread() + "get resource2");
    try {
     Thread.sleep(1000);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    System.out.println(Thread.currentThread() + "waiting get resource1");
    synchronized (resource1) {
     System.out.println(Thread.currentThread() + "get resource1");
    }
   }
  }, "線程 2").start();
 }
}

Output

Thread[線程 1,5,main]get resource1
Thread[線程 2,5,main]get resource2
Thread[線程 1,5,main]waiting get resource2
Thread[線程 2,5,main]waiting get resource1

線程 A 通過 synchronized (resource1) 獲得 resource1 的監(jiān)視器鎖,然后通過Thread.sleep(1000);讓線程 A 休眠 1s 為的是讓線程 B 得到執(zhí)行然后獲取到 resource2 的監(jiān)視器鎖。線程 A 和線程 B 休眠結束了都開始企圖請求獲取對方的資源,然后這兩個線程就會陷入互相等待的狀態(tài),這也就產(chǎn)生了死鎖。上面的例子符合產(chǎn)生死鎖的四個必要條件。

學過操作系統(tǒng)的朋友都知道產(chǎn)生死鎖必須具備以下四個條件:

  1. 互斥條件:該資源任意一個時刻只由一個線程占用。
  2. 請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
  3. 不剝奪條件:線程已獲得的資源在末使用完之前不能被其他線程強行剝奪,只有自己使用完畢后才釋放資源。
  4. 循環(huán)等待條件:若干進程之間形成一種頭尾相接的循環(huán)等待資源關系。

如何避免線程死鎖?

我們只要破壞產(chǎn)生死鎖的四個條件中的其中一個就可以了。

  • 破壞互斥條件

這個條件我們沒有辦法破壞,因為我們用鎖本來就是想讓他們互斥的(臨界資源需要互斥訪問)。

  • 破壞請求與保持條件

一次性申請所有的資源。

  • 破壞不剝奪條件

占用部分資源的線程進一步申請其他資源時,如果申請不到,可以主動釋放它占有的資源。

  • 破壞循環(huán)等待條件

靠按序申請資源來預防。按某一順序申請資源,釋放資源則反序釋放。破壞循環(huán)等待條件。

我們對線程 2 的代碼修改成下面這樣就不會產(chǎn)生死鎖了。

new Thread(() -> {
   synchronized (resource1) {
    System.out.println(Thread.currentThread() + "get resource1");
    try {
     Thread.sleep(1000);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    System.out.println(Thread.currentThread() + "waiting get resource2");
    synchronized (resource2) {
     System.out.println(Thread.currentThread() + "get resource2");
    }
   }
  }, "線程 2").start();

Output

Thread[線程 1,5,main]get resource1
Thread[線程 1,5,main]waiting get resource2
Thread[線程 1,5,main]get resource2
Thread[線程 2,5,main]get resource1
Thread[線程 2,5,main]waiting get resource2
Thread[線程 2,5,main]get resource2

Process finished with exit code 0

我們分析一下上面的代碼為什么避免了死鎖的發(fā)生?

線程 1 首先獲得到 resource1 的監(jiān)視器鎖,這時候線程 2 就獲取不到了。然后線程 1 再去獲取 resource2 的監(jiān)視器鎖,可以獲取到。然后線程 1 釋放了對 resource1、resource2 的監(jiān)視器鎖的占用,線程 2 獲取到就可以執(zhí)行了。這樣就破壞了破壞循環(huán)等待條件,因此避免了死鎖。

以上就是Java中的線程死鎖是什么?如何避免?的詳細內容,更多關于Java 線程死鎖的資料請關注腳本之家其它相關文章!

相關文章

  • Java時間戳類Instant的使用詳解

    Java時間戳類Instant的使用詳解

    這篇文章主要為大家詳細介紹了Java中時間戳類Instant的使用方法,文中的示例代碼講解詳細,對我們學習Java有一定幫助,需要的可以參考一下
    2022-09-09
  • java實現(xiàn)識別二維碼圖片功能方法詳解與實例源碼

    java實現(xiàn)識別二維碼圖片功能方法詳解與實例源碼

    這篇文章主要介紹了java實現(xiàn)識別二維碼圖片,java無法識別二維碼情況下對二維碼圖片調優(yōu)功能方法與實例源碼,需要的朋友可以參考下
    2022-12-12
  • Java怎樣判斷堆區(qū)中的對象可以被回收了

    Java怎樣判斷堆區(qū)中的對象可以被回收了

    文章介紹了Java垃圾回收機制的工作原理,主要通過引用計數(shù)法和可達性分析法來判斷對象是否可以被回收,引用計數(shù)法存在循環(huán)引用問題,而可達性分析法則使用GCRoot對象來判斷對象是否可達,從而決定是否回收,這兩種方法各有優(yōu)缺點,但Java最終采用了可達性分析法來實現(xiàn)垃圾回收
    2024-12-12
  • Jenkins自動部署SpringBoot項目實踐教程

    Jenkins自動部署SpringBoot項目實踐教程

    這篇文章主要介紹了Jenkins自動部署SpringBoot項目實踐教程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 解決出現(xiàn) java.lang.ExceptionInInitializerError錯誤問題

    解決出現(xiàn) java.lang.ExceptionInInitializerError錯誤問題

    這篇文章主要介紹了解決出現(xiàn) java.lang.ExceptionInInitializerError錯誤問題的相關資料,需要的朋友可以參考下
    2017-01-01
  • Springboot?整合?RabbitMQ?消息隊列?詳情

    Springboot?整合?RabbitMQ?消息隊列?詳情

    這篇文章主要介紹了Springboot整合RabbitMQ?消息隊列詳情,文章為榮啊主題展開詳細的內容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-08-08
  • Java中的運算符你知道多少

    Java中的運算符你知道多少

    這篇文章主要為大家詳細介紹了Java中的運算符,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • java8新特性之Optional的深入解析

    java8新特性之Optional的深入解析

    這篇文章主要給大家介紹了關于java8新特性之Optional的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-02-02
  • Java基礎知識之ByteArrayOutputStream流的使用

    Java基礎知識之ByteArrayOutputStream流的使用

    這篇文章主要介紹了Java基礎知識之ByteArrayOutputStream流的使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • 關于ConditionalOnMissingBean失效問題的追蹤

    關于ConditionalOnMissingBean失效問題的追蹤

    這篇文章主要介紹了關于ConditionalOnMissingBean失效問題的追蹤方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03

最新評論

吉首市| 山东省| 仙桃市| 永康市| 车致| 荆门市| 高唐县| 惠来县| 永德县| 双辽市| 林甸县| 铜陵市| 彰武县| 辽宁省| 谷城县| 上虞市| 巍山| 五家渠市| 永城市| 新民市| 林芝县| 临湘市| 浙江省| 莲花县| 屏东县| 萨迦县| 沈丘县| 科技| 秦安县| 沙湾县| 那曲县| 尖扎县| 靖西县| 枝江市| 金昌市| 三门县| 边坝县| 桃源县| 定日县| 苏尼特右旗| 定安县|