3 回答

TA貢獻(xiàn)1828條經(jīng)驗(yàn) 獲得超3個(gè)贊
在Java中,每個(gè)Object
線程都提供了synchronize
在其上鎖定或鎖定線程的能力。同步方法時(shí),該方法將其對(duì)象實(shí)例用作鎖。在您的示例中,方法bow
和bowBack
都屬于synchronized
,并且都位于同一類中Friend
。這意味著任何執(zhí)行這些方法的線程都將在Friend
實(shí)例上作為其鎖進(jìn)行同步。
一系列將導(dǎo)致死鎖的事件是:
第一個(gè)線程調(diào)用開始
alphonse.bow(gaston)
,這是synchronized
在上alphonse
Friend
對(duì)象。這意味著線程必須從該對(duì)象獲取鎖。第二個(gè)線程開始通話
gaston.bow(alphonse)
,這是synchronized
在上gaston
Friend
對(duì)象。這意味著線程必須從該對(duì)象獲取鎖。現(xiàn)在啟動(dòng)的第一個(gè)線程將調(diào)用
bowback
并等待gaston
釋放鎖定。現(xiàn)在啟動(dòng)的第二個(gè)線程將調(diào)用
bowback
并等待alphonse
釋放鎖定。
為了更詳細(xì)地顯示事件的順序:
main()
開始在主要Therad中執(zhí)行(稱為線程1),創(chuàng)建兩個(gè)Friend
實(shí)例。到現(xiàn)在為止還挺好。主線程使用代碼開始其第一個(gè)新線程(稱為線程#2)
new Thread(new Runnable() { ...
。線程#2的呼叫alphonse.bow(gaston)
,這是synchronized
在上alphonse
Friend
對(duì)象。因此,線程#2獲取alphonse
對(duì)象的“鎖” 并進(jìn)入bow
方法。時(shí)間片在這里發(fā)生,原始線程有機(jī)會(huì)進(jìn)行更多處理。
主線程啟動(dòng)第二個(gè)新線程(稱為線程#3),就像第一個(gè)線程一樣。線程#3調(diào)用
gaston.bow(alphonse)
,它在gaston
Friend
對(duì)象上同步。由于還沒(méi)有人獲得gaston
對(duì)象實(shí)例的“鎖”,因此線程#3成功獲取了此鎖并進(jìn)入了bow
方法。一個(gè)時(shí)間片在這里發(fā)生,線程#2有機(jī)會(huì)進(jìn)行更多處理。
線#2現(xiàn)在調(diào)用
bower.bowBack(this);
與bower
正在該實(shí)例的引用gaston
。這在邏輯上等效于的調(diào)用gaston.bowBack(alphonse)
。因此,此方法synchronized
在gaston
實(shí)例上。該對(duì)象的鎖已被獲取,并由另一個(gè)線程(線程3)持有。因此,線程#2必須等待鎖定gaston
被釋放。線程進(jìn)入等待狀態(tài),從而允許線程#3進(jìn)一步執(zhí)行。現(xiàn)在
bowback
,線程#3進(jìn)行了調(diào)用,在這種情況下,它在邏輯上與call相同alphonse.bowBack(gaston)
。為此,它需要獲取alphonse
實(shí)例的鎖,但是此鎖由線程2持有?,F(xiàn)在,該線程已進(jìn)入等待狀態(tài)。
現(xiàn)在,您處于無(wú)法執(zhí)行任何線程的位置。線程#2和線程#3都在等待釋放鎖。但是,如果沒(méi)有Thread進(jìn)展,則無(wú)法釋放任何鎖定。但是,如果沒(méi)有釋放鎖,則任何線程都無(wú)法取得進(jìn)展。
因此:死鎖!
死鎖通常取決于發(fā)生的事件的特定順序,這可能使調(diào)試變得困難,因?yàn)樗鼈兛赡茈y以重現(xiàn)。

TA貢獻(xiàn)1804條經(jīng)驗(yàn) 獲得超2個(gè)贊
同步方法與將所有這些方法代碼包含在
synchronized(this) {
/// code here ...
}
塊。
對(duì)于給定的對(duì)象實(shí)例o,一次只能有一個(gè)線程可以運(yùn)行任何synced(o)塊。嘗試運(yùn)行的所有其他線程都將失敗,直到運(yùn)行該塊(具有同步鎖)的線程退出該塊(放棄鎖)為止。
在您的情況下,死鎖發(fā)生在Alphonse開始在線程1中彎曲時(shí)進(jìn)入同步塊。然后,線程1被系統(tǒng)換出,因此線程2可以啟動(dòng)并進(jìn)行Gaston彎曲。但是Gaston還不能退縮,因?yàn)樗贏lphonse上進(jìn)行同步,并且線程1已經(jīng)具有該鎖。因此它將等待線程1離開該塊。然后,系統(tǒng)將換回線程1,這將嘗試使Alphonse退回。除非它不能這樣做,因?yàn)榫€程2在Gaston上具有同步鎖?,F(xiàn)在這兩個(gè)線程都被卡住,等待另一個(gè)線程完成彎曲,然后才能向后彎曲...

TA貢獻(xiàn)1828條經(jīng)驗(yàn) 獲得超3個(gè)贊
同一對(duì)象的所有同步功能。將方法標(biāo)記為“已同步”與在方法的整個(gè)內(nèi)容周圍放置“已同步(this){”塊非常相似。我之所以不說(shuō)“相同”是因?yàn)槲也恢谰幾g器是否發(fā)出相同的字節(jié)碼,但是AFAIK定義的運(yùn)行時(shí)效果是相同的。
死鎖是經(jīng)典的鎖反轉(zhuǎn)。一個(gè)線程鎖定字母。然后(或同時(shí)在多核系統(tǒng)上),另一個(gè)線程鎖定加斯頓。這部分要求線程的調(diào)度恰好在正確的位置進(jìn)行交織。
然后,每個(gè)線程(以任何順序或同時(shí))嘗試獲取另一個(gè)線程已經(jīng)持有的鎖,因此每個(gè)線程進(jìn)入睡眠狀態(tài)。雙方都不會(huì)喚醒,直到對(duì)方釋放其鎖定,但是雙方都不會(huì)釋放其鎖定,直到對(duì)方喚醒(或終止)。
添加回答
舉報(bào)