身為JAVA工作者必須了解的實(shí)戰(zhàn)知識(shí)(九)

一、死鎖

所謂死鎖: 是指兩個(gè)或兩個(gè)以上的進(jìn)程在執(zhí)行過(guò)程中,因爭(zhēng)奪資源而造成的一種互相等待的現(xiàn)象,若無(wú)外力作用,它們都將無(wú)法推進(jìn)下去。百科百科

當(dāng)兩個(gè)以上的運(yùn)算單元,雙方都在等待對(duì)方停止運(yùn)行,以取得系統(tǒng)資源,但是沒(méi)有一方提前退出時(shí),這種狀況,就稱為死鎖。維基百科

1. 順序死鎖

最少有兩個(gè)鎖,一個(gè)線程獲取到A鎖需要獲取B鎖才能進(jìn)行操作,而另外一個(gè)線程獲取到了B鎖,需要獲取A鎖才能執(zhí)行操作,這種情況下容易出現(xiàn)順序死鎖。

[java]view plaincopy

print?

publicclassLeftRightDeadlock?{

privatefinalObject?left?=newObject();

privatefinalObject?right?=newObject();

publicvoidleftRight()?{

synchronized(left)?{

synchronized(right)?{

//?doSomething();

}

}

}

publicvoidrightLeft()?{

synchronized(right)?{

synchronized(left)?{

//?doSomething();

}

}

}

}

2. 動(dòng)態(tài)的鎖順序死鎖

[java]view plaincopy

print?

publicvoidtransferMoney(Account?fromAccount,?Account?toAccount,?DollarAmount?anount)

throwsInsufficientResourcesException?{

synchronized(fromAccount)?{

synchronized(toAccount)?{

if(fromAccount.getBalance().compareTo(amount)?<0)?{

thrownewInsufficientResourcesException();

}else{

fromAccount.debit(anount);

toAccount.credit(anount);

}

}

}

}

A: transferMoney(myAccount, yourAccount, 10);

B: transferMoney(yourAccount, myAccount, 20);

由外部傳入的變量所有鎖的條件,但是由以上傳入的變量可以看到,這種情況下會(huì)出現(xiàn)一個(gè)線程先獲取myAccount鎖在申請(qǐng)yourAccount鎖,而另外一個(gè)線程相反先獲取yourAccount鎖在申請(qǐng)myAccount鎖。

[java]view plaincopy

print?

privatestaticfinalObject?tieLock?=newObject();

publicvoidtransferMoney(finalAccount?fromAccount,finalAccount?toAccount,finalDollarAmount?anount)

throwsInsufficientResourcesException?{

classHelper{

publicvoidtransfer()throwsInsufficientResourcesException?{

if(fromAccount.getBalance().compareTo(amount)?<0){

thrownewInsufficientResourcesException();

}else{

fromAccount.debit(anount);

toAccount.credit(anount);

}

}

}

intfromHash?=?System.identityHashCode(fromAccount);

inttoHash?=?System.identityHashCode(toAccount);

if(fromHash?<?toHash){

synchronized(fromAccount){

synchronized(toAccount)?{

newHelper().transfer();

}

}

}elseif(fromHash?>??toHash){

synchronized(toAccount){

synchronized(fromAccount)?{

newHelper().transfer();

}

}

}else{

synchronized(tieLock)?{

synchronized(fromAccount)?{

synchronized(toAccount)?{

newHelper().transfer();

}

}

}

}

}

3. 在協(xié)作對(duì)象之間發(fā)生的死鎖

[java]view plaincopy

print?

classTaxi?{

privatePoint?location,?destination;

privatefinalDispatcher?dispatcher;

publicTaxi(Dispatcher?dispatcher)?{

this.dispatcher?=?dispatcher;

}

publicsynchronizedPoint?getLocation(){

returnlocation;

}

publicsynchronizedvoidsetLocation(Point?location){

this.location?=?location;

if(location.equals(destination)){

dispatcher.notifyAvaliable(this);

}

}

}

classDispatcher?{

privatefinalSet?taxis;

privatefinalSet?avaliableTaxis;

publicDispatcher(){

taxis?=newHashSet();

avaliableTaxis?=newHashSet();

}

publicsynchronizedvoidnotifyAvaliable(Taxi?taxi)?{

avaliableTaxis.add(taxi);

}

publicsynchronizedImage?getImage(){

Image?image?=newImage();

for(Taxi?t?:taxis){

image.drawMarker(t.getLocation());

}

returnimage;

}

}

4. 開(kāi)放調(diào)用

-- 待填充

5. 資源死鎖

外部鎖常被忽視而導(dǎo)致死鎖,例如數(shù)據(jù)庫(kù)的鎖

二、死鎖的避免與診斷

1. 支持定時(shí)的死鎖

存在一些預(yù)防死鎖的手段,比如Lock的tryLock,JDK 7中引入的Phaser等。

2. 通過(guò)線程轉(zhuǎn)儲(chǔ)信息來(lái)分析死鎖

通過(guò)Dump線程的StackTrace,例如linux下執(zhí)行命令 kill -3 ,或者jstack –l ,或者使用Jconsole連接上去查看線程的StackTrace,由此來(lái)診斷死鎖問(wèn)題。

三、其他活躍性危險(xiǎn)

1. 饑餓

2. 糟糕的響應(yīng)性

3. 活鎖

四、鎖的使用

使用支持CAS的數(shù)據(jù)結(jié)構(gòu),避免使用鎖,如:AtomicXXX、ConcurrentMap、CopyOnWriteList、ConcurrentLinkedQueue

死鎖經(jīng)常是無(wú)法完全避免的,鴕鳥(niǎo)策略被很多基礎(chǔ)框架所采用。

存在檢測(cè)死鎖的辦法

以上就是我推薦給Java開(kāi)發(fā)者們的一面試經(jīng)典知識(shí)。但是這些知識(shí)里面并沒(méi)有太多Java全棧、Java晉階、JAVA架構(gòu)之類的題,不是我不推薦,而是希望大家更多的從基本功做起,打好基礎(chǔ),太多復(fù)雜的內(nèi)容一會(huì)兒也說(shuō)不明白。

好了同學(xué)們,我能介紹的也都全部介紹完給你們了,如果下獲得更多JAVA教學(xué)資源,可以選擇來(lái)我們這里共同交流,群:240448376,很多大神在這里切磋學(xué)習(xí),不懂可以直接問(wèn),晚上還有大牛免費(fèi)直播教學(xué)。

注:加群要求

1、具有一定工作經(jīng)驗(yàn)的,面對(duì)目前流行的技術(shù)不知從何下手,需要突破技術(shù)瓶頸的可以加,有些應(yīng)屆生和實(shí)習(xí)生也可以加。

2、在公司待久了,過(guò)得很安逸,但跳槽時(shí)面試碰壁。需要在短時(shí)間內(nèi)進(jìn)修、跳槽拿高薪的可以加。

3、如果沒(méi)有工作經(jīng)驗(yàn),但基礎(chǔ)非常扎實(shí),對(duì)java工作機(jī)制,常用設(shè)計(jì)思想,常用java開(kāi)發(fā)框架掌握熟練的,可以加。

4、覺(jué)得自己很牛B,一般需求都能搞定。但是所學(xué)的知識(shí)點(diǎn)沒(méi)有系統(tǒng)化,很難在技術(shù)領(lǐng)域繼續(xù)突破的可以加。

5.阿里Java高級(jí)大牛直播講解知識(shí)點(diǎn),分享知識(shí),多年工作經(jīng)驗(yàn)的梳理和總結(jié),帶著大家全面、科學(xué)地建立自己的技術(shù)體系和技術(shù)認(rèn)知!

PS:現(xiàn)在主要講解的內(nèi)容是(反射原理、枚舉原理與應(yīng)用、注解原理、常用設(shè)計(jì)模式、正規(guī)表達(dá)式高級(jí)應(yīng)用、JAVA操作Office原理詳解JAVA圖像處理技術(shù),等多個(gè)知識(shí)點(diǎn)的詳解和實(shí)戰(zhàn))

6.小號(hào)或者小白之類加群一律不給過(guò),謝謝。

最后,每一位讀到這里的網(wǎng)友,感謝你們能耐心地看完。覺(jué)得對(duì)你有幫助可以給個(gè)喜歡!希望在成為一名更優(yōu)秀的Java程序員的道路上,我們可以一起學(xué)習(xí)、一起進(jìn)步

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容