Java模擬死鎖發生之演繹哲學家進餐問題案例詳解
阿新 • • 發佈:2020-01-07
本文例項講述了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程式設計有所幫助。