Java模擬死鎖發(fā)生之演繹哲學(xué)家進(jìn)餐問題案例詳解
本文實(shí)例講述了Java模擬死鎖發(fā)生之演繹哲學(xué)家進(jìn)餐問題。分享給大家供大家參考,具體如下:
一 點(diǎn)睛
常見的死鎖形式:當(dāng)線程1已經(jīng)占據(jù)資源R1,并持有資源R1上的鎖,而且還在等待資源R2的鎖;而線程2已經(jīng)占據(jù)資源R2,并且持有資源R2上的鎖,卻正在等待資源R1上的鎖。如果兩個(gè)線程不釋放自己占據(jù)的資源鎖,而且還申請(qǐng)對(duì)方資源上的鎖,申請(qǐng)不到時(shí)只能等待,而且它們只能永遠(yuǎn)的等待下去。
二 實(shí)戰(zhàn)
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("守護(hù)線程:程序仍在運(yùn)行中..."); } } }
2 運(yùn)行
Thread-1拿起了餐刀, 等待叉子......
Thread-2拿起了叉子, 等待餐刀......
守護(hù)線程:程序仍在運(yùn)行中...
守護(hù)線程:程序仍在運(yùn)行中...
守護(hù)線程:程序仍在運(yùn)行中...
守護(hù)線程:程序仍在運(yùn)行中...
守護(hù)線程:程序仍在運(yùn)行中...
三 預(yù)防死鎖
1 解決方法
如果規(guī)定線程A和B都必須先拿刀,再拿叉,就不會(huì)發(fā)生死鎖。
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("守護(hù)線程:程序仍在運(yùn)行中..."); } } }
3 運(yùn)行
Thread-1拿起了餐刀, 等待叉子......
守護(hù)線程:程序仍在運(yùn)行中...
守護(hù)線程:程序仍在運(yùn)行中...
Thread-1又拿起了叉子,吃飯中...
Thread-2拿起了餐刀, 等待叉子......
Thread-2又拿起了叉子,吃飯中...
更多java相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java進(jìn)程與線程操作技巧總結(jié)》、《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點(diǎn)技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對(duì)大家java程序設(shè)計(jì)有所幫助。
相關(guān)文章
Java網(wǎng)絡(luò)編程之UDP協(xié)議詳細(xì)解讀
這篇文章主要介紹了Java網(wǎng)絡(luò)編程之UDP協(xié)議詳細(xì)解讀,UDP協(xié)議全稱是用戶數(shù)據(jù)報(bào)協(xié)議,在網(wǎng)絡(luò)中它與TCP協(xié)議一樣用于處理數(shù)據(jù)包,是一種無連接的協(xié)議,在OSI模型中,在第四層——傳輸層,處于IP協(xié)議的上一層,需要的朋友可以參考下2023-12-12SpringBoot 中實(shí)現(xiàn)跨域的5種方式小結(jié)
這篇文章主要介紹了SpringBoot 中實(shí)現(xiàn)跨域的5種方式小結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02SpringBoot實(shí)現(xiàn)第一次啟動(dòng)時(shí)自動(dòng)初始化數(shù)據(jù)庫(kù)的方法
本文主要介紹了SpringBoot實(shí)現(xiàn)第一次啟動(dòng)時(shí)自動(dòng)初始化數(shù)據(jù)庫(kù)的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05