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