摘要:如果線程已經(jīng)獲得鎖,還要獲得鎖,同時(shí)線程已經(jīng)獲得鎖,還要獲得鎖,那么線程和就會(huì)一直阻塞住。
上文講到synchronized關(guān)鍵字在多線程中的使用,既然用到了鎖,就會(huì)有出現(xiàn)死鎖的情況。一個(gè)線程獲得鎖,如果其他線程也想獲得同樣的鎖就會(huì)阻塞住,等待鎖的釋放。如果線程A已經(jīng)獲得鎖1,還要獲得鎖2,同時(shí)線程B已經(jīng)獲得鎖2,還要獲得鎖1,那么線程A和B就會(huì)一直阻塞住。
例子依照慣例先舉個(gè)例子:
public class Test { public static void main(String[] args) throws InterruptedException { Object lock1 = new Object(); Object lock2 = new Object(); Thread t1 = new Thread(new Test().new Tt1(lock1, lock2)); Thread t2 = new Thread(new Test().new Tt2(lock1, lock2)); t1.start(); t2.start(); } class Tt1 implements Runnable{ private Object lock1; private Object lock2; public Tt1(Object lock1,Object lock2) { this.lock1 = lock1; this.lock2 = lock2; } @Override public void run() { synchronized (lock1) { System.out.println(this.getClass()+"-------1"); try { Thread.sleep(1000); synchronized (lock2) { System.out.println(this.getClass()+"-------2"); } } catch (InterruptedException e) { e.printStackTrace(); } } } } class Tt2 implements Runnable{ private Object lock1; private Object lock2; public Tt2(Object lock1,Object lock2) { this.lock1 = lock1; this.lock2 = lock2; } @Override public void run() { synchronized (lock2) { System.out.println(this.getClass()+"-------1"); try { Thread.sleep(1000); synchronized (lock1) { System.out.println(this.getClass()+"-------2"); } } catch (InterruptedException e) { e.printStackTrace(); } } } } }
執(zhí)行結(jié)果:
class Test$Tt1-------1 class Test$Tt2-------1
2個(gè)線程都只執(zhí)行到了第一步,就沒有往下執(zhí)行,都處于了阻塞狀態(tài),這就是死鎖。
定位死鎖死鎖問(wèn)題并不是一個(gè)容易被發(fā)現(xiàn)和定位的問(wèn)題,如果系統(tǒng)出現(xiàn)死鎖問(wèn)題,該如何定位?
1.使用jps,查詢java虛擬機(jī)的pid
2.使用jstack打印堆棧
以Thread-1為例介紹下每一部分的意思
1).Thread-1 線程名稱
2).prio=5 線程優(yōu)先級(jí)
3).os_prio=0 本地的優(yōu)先級(jí)
4).tid=0x000000001929b800 線程id
5).nid=0xfb34 本地的線程id
6)
java.lang.Thread.State: BLOCKED (on object monitor)
線程狀態(tài)處于阻塞
7) waiting to lock <0x00000000d5dd0c38> (a java.lang.Object)正在等待的鎖
8)locked <0x00000000d5dd0c48> (a java.lang.Object) 已獲取的鎖
現(xiàn)在我們可以看到Thread-1和Thread-0都處于阻塞狀態(tài),Thread-1獲取了‘0x00000000d5dd0c48’鎖,等待‘0x00000000d5dd0c38’鎖,而Thread-0則剛好相反。
避免死鎖我們已經(jīng)知道了死鎖的形成和定位,再來(lái)講講如何避免:
1.盡量在線程中不嵌套獲取多個(gè)資源,但你只需獲取一個(gè)時(shí)就不會(huì)出現(xiàn)死鎖、
2.如果不得不嵌套使用時(shí),要多考慮嵌套的順序
3.死鎖是因?yàn)闊o(wú)限的阻塞等待,如果能有一個(gè)最大的等待時(shí)間就可以解決這個(gè)問(wèn)題。synchronized不具備這個(gè)功能,但是我們可以使用Lock類中的tryLock方法去嘗試獲取鎖,這個(gè)方法可以指定一個(gè)超時(shí)時(shí)限,在等待超過(guò)該時(shí)限之后返回失敗信息
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/76377.html
摘要:一個(gè)進(jìn)程可以有多個(gè)線程。線程又叫做輕量級(jí)進(jìn)程。這樣兩個(gè)進(jìn)程相互無(wú)休止地等待下去,均無(wú)法繼續(xù)執(zhí)行,此時(shí)兩個(gè)進(jìn)程陷入死鎖狀態(tài)。不剝奪條件進(jìn)程所獲得的資源在未使用完畢之前,不能被其他進(jìn)程強(qiáng)行奪走,即只能由獲得該資源的進(jìn)程自己來(lái)釋放只能是主動(dòng)釋放。 歡迎進(jìn)入JAVA基礎(chǔ)課程 博客地址:https://blog.csdn.net/houjiyu...本系列文章將主要針對(duì)JAVA一些基礎(chǔ)知識(shí)點(diǎn)進(jìn)...
摘要:一個(gè)進(jìn)程可以有多個(gè)線程。線程又叫做輕量級(jí)進(jìn)程。這樣兩個(gè)進(jìn)程相互無(wú)休止地等待下去,均無(wú)法繼續(xù)執(zhí)行,此時(shí)兩個(gè)進(jìn)程陷入死鎖狀態(tài)。不剝奪條件進(jìn)程所獲得的資源在未使用完畢之前,不能被其他進(jìn)程強(qiáng)行奪走,即只能由獲得該資源的進(jìn)程自己來(lái)釋放只能是主動(dòng)釋放。 歡迎進(jìn)入JAVA基礎(chǔ)課程 博客地址:https://blog.csdn.net/houjiyu...本系列文章將主要針對(duì)JAVA一些基礎(chǔ)知識(shí)點(diǎn)進(jìn)...
摘要:但是并不是什么多線程就可以隨便用,有的時(shí)候多線程反而會(huì)造成系統(tǒng)的負(fù)擔(dān),而且多線程還會(huì)造成其他的數(shù)據(jù)問(wèn)題,下面就來(lái)介紹一下多線程面臨的問(wèn)題。下面這張圖是多線程運(yùn)行時(shí)候的情況,我們發(fā)現(xiàn)上下文切換的次數(shù)暴增。 并發(fā)的概念: 在Java中是支持多線程的,多線程在有的時(shí)候可以大提高程序的速度,比如你的程序中有兩個(gè)完全不同的功能操作,你可以讓兩個(gè)不同的線程去各自執(zhí)行這兩個(gè)操作,互不影響,不需要執(zhí)行...
摘要:并發(fā)和并行并發(fā)和并行是兩個(gè)非常容易被混淆的概念。并發(fā)說(shuō)的是在一個(gè)時(shí)間段內(nèi),多件事情在這個(gè)時(shí)間段內(nèi)交替執(zhí)行。并行說(shuō)的是多件事情在同一個(gè)時(shí)刻同事發(fā)生。由于線程池是一個(gè)線程,得不到執(zhí)行,而被餓死,最終導(dǎo)致了程序死鎖的現(xiàn)象。 同步(Synchronous)和異步(Asynchronous) 同步和異步通常來(lái)形容一次方法調(diào)用,同步方法調(diào)用一旦開始,調(diào)用者必須等到方法調(diào)用返回后,才能繼續(xù)后續(xù)的行為...
摘要:超詳細(xì)的面試題總結(jié)一之基本知識(shí)多線程和虛擬機(jī)創(chuàng)建線程有幾種不同的方式你喜歡哪一種為什么繼承類實(shí)現(xiàn)接口應(yīng)用程序可以使用框架來(lái)創(chuàng)建線程池實(shí)現(xiàn)接口。死亡線程方法執(zhí)行結(jié)束,或者因異常退出了方法,則該線程結(jié)束生命周期。死亡的線程不可再次復(fù)生。 超詳細(xì)的Java面試題總結(jié)(一)之Java基本知識(shí) 多線程和Java虛擬機(jī) 創(chuàng)建線程有幾種不同的方式?你喜歡哪一種?為什么? 繼承Thread類 實(shí)現(xiàn)R...
閱讀 2071·2021-11-11 16:54
閱讀 2140·2019-08-30 15:55
閱讀 3642·2019-08-30 15:54
閱讀 419·2019-08-30 15:44
閱讀 2258·2019-08-30 10:58
閱讀 457·2019-08-26 10:30
閱讀 3077·2019-08-23 14:46
閱讀 3248·2019-08-23 13:46