如何避免Java线程中的死锁?
如何避免Java死鎖? 是Java面試中最受歡迎的問(wèn)題之一,也是本季多線程的風(fēng)格,主要是在高層提出,并帶有很多后續(xù)問(wèn)題。 盡管問(wèn)題看起來(lái)很基礎(chǔ),但是一旦您開(kāi)始深入研究,大多數(shù)Java開(kāi)發(fā)人員就會(huì)陷入困境。
面試問(wèn)題始于“什么是僵局?”
當(dāng)兩個(gè)或多個(gè)線程正在等待彼此釋放所需的資源(鎖定)并無(wú)限期陷入困境時(shí),答案很簡(jiǎn)單,這種情況稱(chēng)為死鎖。 它只會(huì)在多任務(wù) 或多線程的情況下發(fā)生。
如何檢測(cè)Java中的死鎖?
盡管這可能會(huì)有很多答案,但我的版本是:如果我看到一個(gè)嵌套的同步塊或從另一個(gè)調(diào)用一個(gè)同步方法,或者試圖鎖定另一個(gè)對(duì)象,那么我將看一下代碼,那么很有可能發(fā)生死鎖如果開(kāi)發(fā)人員不是很謹(jǐn)慎。
另一種方法是在運(yùn)行應(yīng)用程序時(shí)實(shí)際上陷入僵局時(shí)找到它,嘗試進(jìn)行線程轉(zhuǎn)儲(chǔ),在Linux中,您可以通過(guò)“ kill -3”命令執(zhí)行此操作,這將在應(yīng)用程序日志文件中打印所有線程的狀態(tài)您可以看到哪個(gè)線程鎖定在哪個(gè)對(duì)象上。
您可以使用fastthread.io之類(lèi)的工具來(lái)分析該線程轉(zhuǎn)儲(chǔ),該工具允許您上載線程轉(zhuǎn)儲(chǔ)并進(jìn)行分析。
另一種方法是使用jConsole / VisualVM ,它將確切顯示正在鎖定的線程以及在哪個(gè)對(duì)象上。
編寫(xiě)Java程序會(huì)導(dǎo)致死鎖?
一旦回答了前面的問(wèn)題,他們可能會(huì)要求您編寫(xiě)代碼,這會(huì)導(dǎo)致Java死鎖?
這是我的版本之一:
/*** Java program to create a deadlock by imposing circular wait.* * @author WINDOWS 8**/ public class DeadLockDemo {/** This method request two locks, first String and then Integer*/public void method1() {synchronized (String.class) {System.out.println("Aquired lock on String.class object");synchronized (Integer.class) {System.out.println("Aquired lock on Integer.class object");}}}/** This method also requests same two lock but in exactly* Opposite order i.e. first Integer and then String. * This creates potential deadlock, if one thread holds String lock* and other holds Integer lock and they wait for each other, forever.*/public void method2() {synchronized (Integer.class) {System.out.println("Aquired lock on Integer.class object");synchronized (String.class) {System.out.println("Aquired lock on String.class object");}}} }如果method1()和method2()都將被兩個(gè)或多個(gè)線程調(diào)用,則死鎖的可能性很大,因?yàn)槿绻€程1在執(zhí)行method1()時(shí)獲得Sting對(duì)象的鎖,而線程2在執(zhí)行method2時(shí)獲得Integer對(duì)象的鎖, () 都將互相等待,以釋放對(duì)Integer的鎖定 ,而String繼續(xù)進(jìn)行下去,這將永遠(yuǎn)不會(huì)發(fā)生。
此圖準(zhǔn)確地演示了我們的程序,其中一個(gè)線程在一個(gè)對(duì)象上持有一個(gè)鎖,然后等待另一線程持有的其他對(duì)象鎖。
您會(huì)看到線程1想要鎖定對(duì)象2的鎖,該對(duì)象2由線程2持有,而線程2想要鎖定對(duì)象1的鎖,該對(duì)象1由線程1持有。由于沒(méi)有線程愿意放棄,因此存在死鎖,并且線程2 Java程序被卡住。
如何避免Java死鎖?
現(xiàn)在,面試官進(jìn)入最后一部分,在我看來(lái),這是最重要的部分。
您如何解決代碼中的死鎖? 或如何避免Java中的死鎖?
如果您仔細(xì)查看了上面的代碼,那么您可能已經(jīng)發(fā)現(xiàn)造成死鎖的真正原因不是多個(gè)線程,而是它們請(qǐng)求鎖定的方式,如果您提供有序訪問(wèn),那么問(wèn)題將得到解決。
這是我的固定版本,它通過(guò)無(wú)效循環(huán)的循環(huán)等待來(lái)避免死鎖, 而沒(méi)有搶占 ,這是需要死鎖的四個(gè)條件之一。
public class DeadLockFixed {/*** Both method are now requesting lock in same order, first Integer and then String.* You could have also done reverse e.g. first String and then Integer,* both will solve the problem, as long as both method are requesting lock* in consistent order.*/public void method1() {synchronized (Integer.class) {System.out.println("Aquired lock on Integer.class object");synchronized (String.class) {System.out.println("Aquired lock on String.class object");}}}public void method2() {synchronized (Integer.class) {System.out.println("Aquired lock on Integer.class object");synchronized (String.class) {System.out.println("Aquired lock on String.class object");}}} }現(xiàn)在將沒(méi)有任何死鎖,因?yàn)檫@兩個(gè)方法都以相同的順序訪問(wèn)Integer和String類(lèi)文字的鎖。 因此,如果線程A獲得了對(duì)Integer對(duì)象的鎖定,則線程B直到線程A釋放Integer鎖定后才會(huì)繼續(xù)進(jìn)行,即使線程B持有字符串鎖,線程A也不會(huì)被阻塞,因?yàn)楝F(xiàn)在線程B不會(huì)期望線程A釋放整數(shù)鎖可繼續(xù)進(jìn)行。
感謝您閱讀本文。 如果您喜歡這篇文章,請(qǐng)與您的朋友和同事分享。 如果您有任何疑問(wèn)或反饋,請(qǐng)留言。
翻譯自: https://www.javacodegeeks.com/2018/08/avoid-deadlock-java-threads.html
總結(jié)
以上是生活随笔為你收集整理的如何避免Java线程中的死锁?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 迁移学习 简而言之_简而言之Java.i
- 下一篇: 均方根误差有没有单位_1千万年仅误差一秒