您好,登錄后才能下訂單哦!
?多線程是Java工程師進階所必須掌握的一項技能,也是面試中繞不過的一個環(huán)節(jié),而死鎖又是多線程同步失敗的經(jīng)典案例,對于復(fù)雜的系統(tǒng),死鎖是很難通過代碼層面來做靜態(tài)檢測和排查的,所以有的面試官會從反向出發(fā),讓你手寫一個死鎖程序。
????先來看一個網(wǎng)絡(luò)上常見的死鎖程序(可能存在問題):
public?class?DeadLockTest?{????private?static?Object?lock1?=?new?Object();????private?static?Object?lock2?=?new?Object();????public?static?void?main(String[]?args)?{????????new?Thread(()?->?{ ????????????synchronized?(lock1)?{ ????????????????System.out.println("thread1?acquired?lock1");????????????????try?{ ????????????????????Thread.sleep(1000); ????????????????}?catch?(InterruptedException?e)?{ ????????????????????e.printStackTrace(); ????????????????} ????????????????System.out.println("thread1?try?to?acquire?lock2"); ????????????????synchronized?(lock2)?{ ????????????????????System.out.println("thread1?acquired?lock2"); ????????????????} ????????????} ????????},?"t1").start();????????new?Thread(()?->?{ ????????????synchronized?(lock2)?{ ????????????????System.out.println("thread2?acquired?lock2");????????????????try?{ ????????????????????Thread.sleep(1000); ????????????????}?catch?(InterruptedException?e)?{ ????????????????????e.printStackTrace(); ????????????????} ????????????????System.out.println("thread2?try?to?acquire?lock1"); ????????????????synchronized?(lock1)?{ ????????????????????System.out.println("thread2?acquired?lock1"); ????????????????} ????????????} ????????},?"t2").start();???????? ????????//?檢測死鎖 ????????checkDeadLock(); ????????System.out.println("main?thread?end"); ????}????public?static?void?checkDeadLock()?{ ????????ThreadMXBean?mxBean?=?ManagementFactory.getThreadMXBean(); ????????ScheduledExecutorService?scheduled?=?Executors.newScheduledThreadPool(1);????????//?初始等待5秒,每隔10秒檢測一次 ????????scheduled.scheduleAtFixedRate(()->{????????????long[]?threadIds?=?mxBean.findDeadlockedThreads();????????????if?(threadIds?!=?null)?{ ????????????????System.out.println("檢測到死鎖線程:"); ????????????????ThreadInfo[]?threadInfos?=?mxBean.getThreadInfo(threadIds);????????????????for?(ThreadInfo?info?:?threadInfos)?{ ????????????????????System.out.println(info.getThreadId()?+?":"?+?info.getThreadName()); ????????????????} ????????????} ????????},?5L,?10L,?TimeUnit.SECONDS); ????} }
????上面這段程序在99.99%的情況下都會發(fā)生死鎖,但是從理論的角度來講,死鎖并不是100%會發(fā)生的,比如:線程t1先啟動并獲取了鎖lock1,在休眠的這1s的過程中,JVM并未發(fā)生線程調(diào)度(實際上基本不可能),t2未得到執(zhí)行也未獲取到鎖lock2,這時候t1休眠結(jié)束繼續(xù)執(zhí)行并獲取了鎖lock2,那么這種情況下就不會發(fā)生死鎖了。
????如何寫一個100%會發(fā)生死鎖的程序呢?直接上代碼:
public?class?DeadLockTest?{????private?static?Object?lock1?=?new?Object();????private?static?Object?lock2?=?new?Object();????//?這里的flag需要用volatile修飾,以保證線程間的可見性 ????private?static?volatile?boolean?flag1?=?false;????private?static?volatile?boolean?flag2?=?false;????public?static?void?main(String[]?args)?{????????new?Thread(()?->?{ ????????????synchronized?(lock1)?{ ????????????????flag1?=?true; ????????????????System.out.println("thread1?acquired?lock1");????????????????while?(!flag2)?{????????????????????//?無限循環(huán),等待thread2獲取到lock2后再繼續(xù)往下執(zhí)行(相比使用Thread.sleep(1000)在理論上是100%會出現(xiàn)死鎖) ????????????????????Thread.yield(); ????????????????} ????????????????System.out.println("thread1?try?to?acquire?lock2"); ????????????????synchronized?(lock2)?{ ????????????????????System.out.println("thread1?acquired?lock2"); ????????????????} ????????????} ????????},?"t1").start();????????new?Thread(()?->?{ ????????????synchronized?(lock2)?{ ????????????????flag2?=?true; ????????????????System.out.println("thread2?acquired?lock2");????????????????while?(!flag1)?{ ????????????????????Thread.yield(); ????????????????} ????????????????System.out.println("thread2?try?to?acquire?lock1"); ????????????????synchronized?(lock1)?{ ????????????????????System.out.println("thread2?acquired?lock1"); ????????????????} ????????????} ????????},?"t2").start();????????//?檢測死鎖 ????????checkDeadLock(); ????????System.out.println("main?thread?end"); ????}????public?static?void?checkDeadLock()?{ ????????ThreadMXBean?mxBean?=?ManagementFactory.getThreadMXBean(); ????????ScheduledExecutorService?scheduled?=?Executors.newScheduledThreadPool(1);????????//?初始等待5秒,每隔10秒檢測一次 ????????scheduled.scheduleAtFixedRate(()?->?{????????????long[]?threadIds?=?mxBean.findDeadlockedThreads();????????????if?(threadIds?!=?null)?{ ????????????????System.out.println("檢測到死鎖線程:"); ????????????????ThreadInfo[]?threadInfos?=?mxBean.getThreadInfo(threadIds);????????????????for?(ThreadInfo?info?:?threadInfos)?{ ????????????????????System.out.println(info.getThreadId()?+?":"?+?info.getThreadName()); ????????????????} ????????????} ????????},?5L,?10L,?TimeUnit.SECONDS); ????} }
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。