摘要:本人郵箱歡迎轉(zhuǎn)載轉(zhuǎn)載請注明網(wǎng)址代碼已經(jīng)全部托管有需要的同學(xué)自行下載引言多線程如果設(shè)計的不合理的話很可能就會出現(xiàn)死鎖當(dāng)兩個或者多個線程同事想要去獲取共享資源的鎖時但每個線程都要等其他線程把他們各自的鎖給釋放才能繼續(xù)運(yùn)行這就是死鎖出現(xiàn)死鎖必須具
引言本人郵箱:
歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明網(wǎng)址 http://blog.csdn.net/tianshi_kco
github: https://github.com/kco1989/kco
代碼已經(jīng)全部托管github有需要的同學(xué)自行下載
多線程如果設(shè)計的不合理的話,很可能就會出現(xiàn)死鎖.當(dāng)兩個或者多個線程同事想要去獲取共享資源的鎖時,但每個線程都要等其他線程把他們各自的鎖給釋放,才能繼續(xù)運(yùn)行,這就是死鎖.出現(xiàn)死鎖必須具備以下幾點
要有兩個或兩個以上的線程
至少有兩個共享資源的鎖
至少存在兩個線程各自擁有一個鎖
現(xiàn)在這兩個線程在等待獲取彼此的鎖,這就出現(xiàn)死鎖了
比如Thread1
synchronized(A){ //Thread1 執(zhí)行到這里 synchronized(B){ ... } }
Thread2
synchronized(B){ //Thread2 執(zhí)行到這里 synchronized(A){ ... } }
以上這種情況就是死鎖,如果是兩個線程出現(xiàn)死鎖,問題可能還比較好找.更復(fù)雜是有多個線程,比如線程n各自擁有鎖n,然后線程1到線程n-1,正在請求獲取鎖n+1,而線程n正在請求獲取鎖1,這樣也或出現(xiàn)死鎖,而且還更難被發(fā)現(xiàn).
例子我們要看一個例子
public class Demo1 { public static void main(String[] args) { Object bigGate = new Object(); Object smallGate = new Object(); new Thread(new Runnable() { @Override public void run() { String name = Thread.currentThread().getName(); synchronized (bigGate){ System.out.println(name + ":我把大門給鎖了...然后我休息一下..."); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(name + ":我現(xiàn)在要進(jìn)入小門....."); synchronized (smallGate){ System.out.println(name + ":我永遠(yuǎn)都進(jìn)不來啊....."); } } } },"小明").start(); new Thread(new Runnable() { @Override public void run() { String name = Thread.currentThread().getName(); synchronized (smallGate){ System.out.println(name + ":我把小門給鎖了...然后我休息一下..."); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(name + ":我現(xiàn)在要進(jìn)入大門....."); synchronized (bigGate){ System.out.println(name + ":我永遠(yuǎn)都進(jìn)不來啊....."); } } } },"小紅").start(); } }
運(yùn)行結(jié)果
小明我把大門給鎖了...然后我休息一下... 小紅我把小門給鎖了...然后我休息一下... 小明:我現(xiàn)在要進(jìn)入小門..... 小紅:我現(xiàn)在要進(jìn)入大門..... //然后程序到這里就一直不動了.....解決辦法
鎖的順序,讓兩個線程獲取鎖的順序是一直,則不會出現(xiàn)死鎖
public class Demo2 { public static void main(String[] args) { Object bigGate = new Object(); Object smallGate = new Object(); new Thread(new Runnable() { @Override public void run() { String name = Thread.currentThread().getName(); synchronized (bigGate){ System.out.println(name + ":我把大門給鎖了...然后我休息一下..."); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(name + ":我現(xiàn)在要進(jìn)入小門....."); synchronized (smallGate){ System.out.println(name + ":我終于進(jìn)來了....."); } } } },"小明").start(); new Thread(new Runnable() { @Override public void run() { String name = Thread.currentThread().getName(); synchronized (bigGate){ System.out.println(name + ":我把大門給鎖了...然后我休息一下..."); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(name + ":我現(xiàn)在要進(jìn)入小門....."); synchronized (smallGate){ System.out.println(name + ":我終于進(jìn)來了....."); } } } },"小紅").start(); } }
運(yùn)行結(jié)果:
小明:我把大門給鎖了...然后我休息一下... 小明:我現(xiàn)在要進(jìn)入小門..... 小明:我終于進(jìn)來了..... 小紅:我把大門給鎖了...然后我休息一下... 小紅:我現(xiàn)在要進(jìn)入小門..... 小紅:我終于進(jìn)來了.....
在獲取鎖的時候加超時時間,這里我們用之前學(xué)的Lock來做例子
public class Demo3 { public static void main(String[] args) { Lock bigGate = new ReentrantLock(); Lock smallGate = new ReentrantLock(); Random random = new Random(); new Thread(new Runnable() { @Override public void run() { String name = Thread.currentThread().getName(); bigGate.lock(); try { System.out.println(name + ":我把大門給鎖了...然后我休息一下..."); Thread.sleep(100); System.out.println(name + ":我現(xiàn)在要進(jìn)入小門....."); if(smallGate.tryLock(random.nextInt(500), TimeUnit.MILLISECONDS)){ try { System.out.println(name + ":我終于進(jìn)來了....."); }finally { smallGate.unlock(); } }else{ System.out.println(name + ":我進(jìn)不去小門,算了,不進(jìn)了..."); } } catch (InterruptedException e) { e.printStackTrace(); } finally { bigGate.unlock(); } } },"小明").start(); new Thread(new Runnable() { @Override public void run() { String name = Thread.currentThread().getName(); smallGate.lock(); try { System.out.println(name + ":我把小門給鎖了...然后我休息一下..."); Thread.sleep(100); System.out.println(name + ":我現(xiàn)在要進(jìn)入大門....."); if(bigGate.tryLock(random.nextInt(500), TimeUnit.MILLISECONDS)){ try { System.out.println(name + ":我終于進(jìn)來了....."); }finally { bigGate.unlock(); } }else{ System.out.println(name + ":我進(jìn)不去大門,算了,不進(jìn)了..."); } } catch (InterruptedException e) { e.printStackTrace(); } finally { smallGate.unlock(); } } },"小紅").start(); } }
運(yùn)行結(jié)果:
小明:我把大門給鎖了...然后我休息一下... 小紅:我把小門給鎖了...然后我休息一下... 小明:我現(xiàn)在要進(jìn)入小門..... 小紅:我現(xiàn)在要進(jìn)入大門..... 小紅:我進(jìn)不去大門,算了,不進(jìn)了... 小明:我終于進(jìn)來了.....
這樣也可以保證不會出現(xiàn)死鎖.
打賞如果覺得我的文章寫的還過得去的話,有錢就捧個錢場,沒錢給我捧個人場(幫我點贊或推薦一下)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/67041.html
摘要:超詳細(xì)的面試題總結(jié)一之基本知識多線程和虛擬機(jī)創(chuàng)建線程有幾種不同的方式你喜歡哪一種為什么繼承類實現(xiàn)接口應(yīng)用程序可以使用框架來創(chuàng)建線程池實現(xiàn)接口。死亡線程方法執(zhí)行結(jié)束,或者因異常退出了方法,則該線程結(jié)束生命周期。死亡的線程不可再次復(fù)生。 超詳細(xì)的Java面試題總結(jié)(一)之Java基本知識 多線程和Java虛擬機(jī) 創(chuàng)建線程有幾種不同的方式?你喜歡哪一種?為什么? 繼承Thread類 實現(xiàn)R...
摘要:我的是忙碌的一年,從年初備戰(zhàn)實習(xí)春招,年三十都在死磕源碼,三月份經(jīng)歷了阿里五次面試,四月順利收到實習(xí)。因為我心理很清楚,我的目標(biāo)是阿里。所以在收到阿里之后的那晚,我重新規(guī)劃了接下來的學(xué)習(xí)計劃,將我的短期目標(biāo)更新成拿下阿里轉(zhuǎn)正。 我的2017是忙碌的一年,從年初備戰(zhàn)實習(xí)春招,年三十都在死磕JDK源碼,三月份經(jīng)歷了阿里五次面試,四月順利收到實習(xí)offer。然后五月懷著忐忑的心情開始了螞蟻金...
摘要:此時線程需要鎖才能繼續(xù)往下執(zhí)行。但是線程的鎖并沒有釋放,線程的鎖也沒有釋放。 前言 只有光頭才能變強(qiáng) 回顧前面: ThreadLocal就是這么簡單 多線程三分鐘就可以入個門了! 多線程基礎(chǔ)必要知識點!看了學(xué)習(xí)多線程事半功倍 Java鎖機(jī)制了解一下 AQS簡簡單單過一遍 Lock鎖子類了解一下 線程池你真不來了解一下嗎? 本篇主要是講解死鎖,這是我在多線程的最后一篇了。主要將多線程...
摘要:但是,有些操作會依賴于對象的變化過程,此時的解決思路一般就是使用版本號。在變量前面追加上版本號,每次變量更新的時候把版本號加一,那么就會變成。四的引入就是上面所說的加了版本號的。 showImg(https://segmentfault.com/img/remote/1460000016012188); 本文首發(fā)于一世流云的專欄:https://segmentfault.com/blo...
摘要:線程間通信其實就是多個線程操作同一個資源,但動作不同。同步前提是多線程。將該線程載入線程池,等待喚醒。該方法拋出異常,故需要配合使用隨機(jī)喚醒線程池中一線程。線程為了檢測死鎖,它需要遞進(jìn)地檢測所有被請求的鎖。 線程間通信 其實就是多個線程操作同一個資源,但動作不同。示例:在某個數(shù)據(jù)庫中,Input輸入人的姓名,性別,Output輸出,兩個線程同時作用。思考:1.明確哪些代碼是多線程操作的...
閱讀 1216·2021-11-22 12:05
閱讀 1343·2021-09-29 09:35
閱讀 640·2019-08-30 15:55
閱讀 3132·2019-08-30 14:12
閱讀 960·2019-08-30 14:11
閱讀 2881·2019-08-30 13:10
閱讀 2406·2019-08-29 16:33
閱讀 3335·2019-08-29 11:02