1. 程式人生 > 程式設計 >Java模擬死鎖發生之演繹哲學家進餐問題案例詳解

Java模擬死鎖發生之演繹哲學家進餐問題案例詳解

本文例項講述了Java模擬死鎖發生之演繹哲學家進餐問題。分享給大家供大家參考,具體如下:

一 點睛

常見的死鎖形式:當執行緒1已經佔據資源R1,並持有資源R1上的鎖,而且還在等待資源R2的鎖;而執行緒2已經佔據資源R2,並且持有資源R2上的鎖,卻正在等待資源R1上的鎖。如果兩個執行緒不釋放自己佔據的資源鎖,而且還申請對方資源上的鎖,申請不到時只能等待,而且它們只能永遠的等待下去。

二 實戰

1 程式碼

public class DeadLockDemo
{
  /** knife鎖 */
  private static String knife = "餐刀"; //臨界資源
  /** fork鎖 */
  private static String fork = "叉子"; //臨界資源
  public static void main(String[] args)
  {
    DaemonThread daemonTh = new DaemonThread();
    Thread newDaemon = new Thread(daemonTh);
    newDaemon.setDaemon(true);
    newDaemon.start();
    new DeadLockDemo().deadLock();
  }
  private void deadLock()
  {
    Thread t1 = new Thread(new Runnable() {
      @Override
      public void run()
      {
        synchronized (knife) {
          System.out.println(Thread.currentThread().getName() + "拿起了" + knife + ",等待" + fork + "......");
          try {
            Thread.sleep(2000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          synchronized (fork) {
            System.out.println(Thread.currentThread().getName() + "又拿起了" + fork + ",吃飯中...");
          }
        }
      }
    });
    Thread t2 = new Thread(new Runnable() {
      @Override
      public void run() {
        synchronized (fork) {
          System.out.println(Thread.currentThread().getName() + "拿起了" + fork + ",等待" + knife + "......");
          synchronized (knife) {
            System.out.println(Thread.currentThread().getName() + "又拿起了" + knife + ",吃飯中...");
          }
        }
      }
    });
    t1.start();
    t2.start();
  }
}
class DaemonThread implements Runnable
{
  @Override
  public void run()
  {
    while(true)
    {
      try {
        Thread.sleep(1000);
      }catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("守護執行緒:程式仍在執行中...");
    }
  }
}

2 執行

Thread-1拿起了餐刀,等待叉子......
Thread-2拿起了叉子,等待餐刀......
守護執行緒:程式仍在執行中...
守護執行緒:程式仍在執行中...
守護執行緒:程式仍在執行中...
守護執行緒:程式仍在執行中...
守護執行緒:程式仍在執行中...

三 預防死鎖

1 解決方法

如果規定執行緒A和B都必須先拿刀,再拿叉,就不會發生死鎖。

2 程式碼

public class DeadLockDemo
{
  /** knife鎖 */
  private static String knife = "餐刀"; //臨界資源
  /** fork鎖 */
  private static String fork = "叉子"; //臨界資源
  public static void main(String[] args)
  {
    DaemonThread daemonTh = new DaemonThread();
    Thread newDaemon = new Thread(daemonTh);
    newDaemon.setDaemon(true);
    newDaemon.start();
    new DeadLockDemo().deadLock();
  }
  private void deadLock()
  {
    Thread t1 = new Thread(new Runnable() {
      @Override
      public void run()
      {
        synchronized (knife) {
          System.out.println(Thread.currentThread().getName() + "拿起了" + knife + ",等待" + fork + "......");
          try {
            Thread.sleep(2000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          synchronized (fork) {
            System.out.println(Thread.currentThread().getName() + "又拿起了" + fork + ",吃飯中...");
          }
        }
      }
    });
    Thread t2 = new Thread(new Runnable() {
      @Override
      public void run() {
        synchronized (knife) {
          System.out.println(Thread.currentThread().getName() + "拿起了" + knife + ",等待" + fork + "......");
          synchronized (fork) {
            System.out.println(Thread.currentThread().getName() + "又拿起了" + fork + ",吃飯中...");
          }
        }
      }
    });
    t1.start();
    t2.start();
  }
}
class DaemonThread implements Runnable
{
  @Override
  public void run()
  {
    while(true)
    {
      try {
        Thread.sleep(1000);
      }catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("守護執行緒:程式仍在執行中...");
    }
  }
}

3 執行

Thread-1拿起了餐刀,等待叉子......
守護執行緒:程式仍在執行中...
守護執行緒:程式仍在執行中...
Thread-1又拿起了叉子,吃飯中...
Thread-2拿起了餐刀,等待叉子......
Thread-2又拿起了叉子,吃飯中...

更多java相關內容感興趣的讀者可檢視本站專題:《Java程序與執行緒操作技巧總結》、《Java資料結構與演算法教程》、《Java操作DOM節點技巧總結》、《Java檔案與目錄操作技巧彙總》和《Java快取操作技巧彙總》

希望本文所述對大家java程式設計有所幫助。