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

Java  解決死鎖的方法實例詳解

 更新時間:2017年04月19日 15:38:39   作者:追夢者_wang  
這篇文章主要介紹了java 多線程死鎖詳解及簡單實例的相關(guān)資料,需要的朋友可以參考下

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

java 死鎖產(chǎn)生的四個必要條件:

1>互斥使用,即當(dāng)資源被一個線程使用(占有)時,別的線程不能使用

2>不可搶占,資源請求者不能強制從資源占有者手中奪取資源,資源只能由資源占有者主動釋放。

3>請求和保持,即當(dāng)資源請求者在請求其他的資源的同時保持對原有資源的戰(zhàn)友。

4>循環(huán)等待,即存在一個等待隊列:P1占有P2的資源,P2占有P3的資源,P3占有P1的資源。這樣就形成了一個等待環(huán)路。

當(dāng)上述四個條件都成立的時候,便形成死鎖。當(dāng)然,死鎖的情況下如果打破上述任何一個條件,便可讓死鎖消失。下面用java代碼來模擬一下死鎖的產(chǎn)生。

解決死鎖問題的方法是:一種是用synchronized,一種是用Lock顯式鎖實現(xiàn)。

而如果不恰當(dāng)?shù)氖褂昧随i,且出現(xiàn)同時要鎖多個對象時,會出現(xiàn)死鎖情況,如下:

/*
 author by w3cschool.cc
 LockTest.java
 */
import java.util.Date;
public class LockTest {
  public static String obj1 = "obj1";
  public static String obj2 = "obj2";
  public static void main(String[] args) {
   LockA la = new LockA();
   new Thread(la).start();
   LockB lb = new LockB();
   new Thread(lb).start();
  }
}
class LockA implements Runnable{
  public void run() {
   try {
     System.out.println(new Date().toString() + " LockA 開始執(zhí)行");
     while(true){
      synchronized (LockTest.obj1) {
        System.out.println(new Date().toString() + " LockA 鎖住 obj1");
        Thread.sleep(3000); // 此處等待是給B能鎖住機會
        synchronized (LockTest.obj2) {
         System.out.println(new Date().toString() + " LockA 鎖住 obj2");
         Thread.sleep(60 * 1000); // 為測試,占用了就不放
        }
      }
     }
   } catch (Exception e) {
     e.printStackTrace();
   }
  }
}
class LockB implements Runnable{
  public void run() {
   try {
     System.out.println(new Date().toString() + " LockB 開始執(zhí)行");
     while(true){
      synchronized (LockTest.obj2) {
        System.out.println(new Date().toString() + " LockB 鎖住 obj2");
        Thread.sleep(3000); // 此處等待是給A能鎖住機會
        synchronized (LockTest.obj1) {
         System.out.println(new Date().toString() + " LockB 鎖住 obj1");
         Thread.sleep(60 * 1000); // 為測試,占用了就不放
        }
      }
     }
   } catch (Exception e) {
     e.printStackTrace();
   }
  }
}

以上代碼運行輸出結(jié)果為:

Tue May 05 10:51:06 CST 2015 LockB 開始執(zhí)行
Tue May 05 10:51:06 CST 2015 LockA 開始執(zhí)行
Tue May 05 10:51:06 CST 2015 LockB 鎖住 obj2
Tue May 05 10:51:06 CST 2015 LockA 鎖住 obj1

此時死鎖產(chǎn)生。

為了解決這個問題,我們不使用顯示的去鎖,我們用信號量去控制。

信號量可以控制資源能被多少線程訪問,這里我們指定只能被一個線程訪問,就做到了類似鎖住。而信號量可以指定去獲取的超時時間,我們可以根據(jù)這個超時時間,去做一個額外處理。

對于無法成功獲取的情況,一般就是重復(fù)嘗試,或指定嘗試的次數(shù),也可以馬上退出。

來看下如下代碼:

/*
 author by w3cschool.cc
 UnLockTest.java
 */
import java.util.Date;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class UnLockTest {
  public static String obj1 = "obj1";
  public static final Semaphore a1 = new Semaphore(1);
  public static String obj2 = "obj2";
  public static final Semaphore a2 = new Semaphore(1);
  public static void main(String[] args) {
   LockAa la = new LockAa();
   new Thread(la).start();
   LockBb lb = new LockBb();
   new Thread(lb).start();
  }
}
class LockAa implements Runnable {
  public void run() {
   try {
     System.out.println(new Date().toString() + " LockA 開始執(zhí)行");
     while (true) {
      if (UnLockTest.a1.tryAcquire(1, TimeUnit.SECONDS)) {
        System.out.println(new Date().toString() + " LockA 鎖住 obj1");
        if (UnLockTest.a2.tryAcquire(1, TimeUnit.SECONDS)) {
         System.out.println(new Date().toString() + " LockA 鎖住 obj2");
         Thread.sleep(60 * 1000); // do something
        }else{
         System.out.println(new Date().toString() + "LockA 鎖 obj2 失敗");
        }
      }else{
        System.out.println(new Date().toString() + "LockA 鎖 obj1 失敗");
      }
      UnLockTest.a1.release(); // 釋放
      UnLockTest.a2.release();
      Thread.sleep(1000); // 馬上進行嘗試,現(xiàn)實情況下do something是不確定的
     }
   } catch (Exception e) {
     e.printStackTrace();
   }
  }
}
class LockBb implements Runnable {
  public void run() {
   try {
     System.out.println(new Date().toString() + " LockB 開始執(zhí)行");
     while (true) {
      if (UnLockTest.a2.tryAcquire(1, TimeUnit.SECONDS)) {
        System.out.println(new Date().toString() + " LockB 鎖住 obj2");
        if (UnLockTest.a1.tryAcquire(1, TimeUnit.SECONDS)) {
         System.out.println(new Date().toString() + " LockB 鎖住 obj1");
         Thread.sleep(60 * 1000); // do something
        }else{
         System.out.println(new Date().toString() + "LockB 鎖 obj1 失敗");
        }
      }else{
        System.out.println(new Date().toString() + "LockB 鎖 obj2 失敗");
      }
      UnLockTest.a1.release(); // 釋放
      UnLockTest.a2.release();
      Thread.sleep(10 * 1000); // 這里只是為了演示,所以tryAcquire只用1秒,而且B要給A讓出能執(zhí)行的時間,否則兩個永遠是死鎖
     }
   } catch (Exception e) {
     e.printStackTrace();
   }
  }
}

以上實例代碼輸出結(jié)構(gòu)為:

Tue May 05 10:59:13 CST 2015 LockA 開始執(zhí)行
Tue May 05 10:59:13 CST 2015 LockB 開始執(zhí)行
Tue May 05 10:59:13 CST 2015 LockB 鎖住 obj2
Tue May 05 10:59:13 CST 2015 LockA 鎖住 obj1
Tue May 05 10:59:14 CST 2015LockB 鎖 obj1 失敗
Tue May 05 10:59:14 CST 2015LockA 鎖 obj2 失敗
Tue May 05 10:59:15 CST 2015 LockA 鎖住 obj1
Tue May 05 10:59:15 CST 2015 LockA 鎖住 obj2

希望本篇內(nèi)容可以幫助到您

相關(guān)文章

  • 23種設(shè)計模式(17)java命令模式

    23種設(shè)計模式(17)java命令模式

    這篇文章主要為大家詳細介紹了23種設(shè)計模式之java命令模式,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • java 實現(xiàn)音樂播放器的簡單實例

    java 實現(xiàn)音樂播放器的簡單實例

    這篇文章主要介紹了java 實現(xiàn)音樂播放器的簡單實例的相關(guān)資料,希望通過本文能幫助到大家,實現(xiàn)這樣的功能,需要的朋友可以參考下
    2017-09-09
  • 解決IDEA2020.1.2IDEA打不開的問題(最新分享)

    解決IDEA2020.1.2IDEA打不開的問題(最新分享)

    由于idea安裝多了某個jar,點擊出現(xiàn)讀條后閃退情況,接下來通過本文給大家分享解決IDEA2020.1.2IDEA打不開的問題,非常不錯,具有一定的參考借鑒價值,感興趣的朋友跟隨小編一起看看吧
    2020-07-07
  • Spring中的@RestControllerAdvice注解使用解析

    Spring中的@RestControllerAdvice注解使用解析

    這篇文章主要介紹了Spring中的@RestControllerAdvice注解使用解析,@RestControllerAdvice?是?Spring?框架中一個用于統(tǒng)一處理控制器異常和返回結(jié)果的注解,它可以被用來定義全局異常處理程序和全局響應(yīng)結(jié)果處理程序,需要的朋友可以參考下
    2024-01-01
  • Java獲取中文拼音、中文首字母縮寫和中文首字母的示例

    Java獲取中文拼音、中文首字母縮寫和中文首字母的示例

    本文主要介紹了Java獲取中文拼音、中文首字母縮寫和中文首字母,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2016-10-10
  • Spring mvc攔截器實現(xiàn)原理解析

    Spring mvc攔截器實現(xiàn)原理解析

    這篇文章主要介紹了Spring mvc攔截器實現(xiàn)原理解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-03-03
  • 2020macOS Big Sur配置Java開發(fā)環(huán)境之jdk安裝過程

    2020macOS Big Sur配置Java開發(fā)環(huán)境之jdk安裝過程

    這篇文章主要介紹了2020macOS Big Sur配置Java開發(fā)環(huán)境之jdk安裝,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • 基于Gradle搭建Spring?5.3.13-release源碼閱讀環(huán)境的詳細流程

    基于Gradle搭建Spring?5.3.13-release源碼閱讀環(huán)境的詳細流程

    這篇文章主要介紹了基于Gradle搭建Spring?5.3.13-release源碼閱讀環(huán)境,首先安裝jdk、gradle等一系列必要操作,本文通過實例代碼相結(jié)合給大家講解的非常詳細,需要的朋友可以參考下
    2022-04-04
  • springboot集成RocketMQ過程及使用示例詳解

    springboot集成RocketMQ過程及使用示例詳解

    這篇文章主要為大家介紹了springboot集成RocketMQ過程及使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-07-07
  • SpringBoot基礎(chǔ)框架詳解

    SpringBoot基礎(chǔ)框架詳解

    SpringBoot開發(fā)目的是為了簡化Spring應(yīng)用的創(chuàng)建、運行、調(diào)試和部署等,使用Spring Boot可以不用或者只需要很少的Spring配置就可以讓企業(yè)項目快速運行起來,本文介紹SpringBoot基礎(chǔ)框架詳解,感興趣的朋友一起看看吧
    2025-05-05

最新評論