1. 死鎖及死鎖的處理策略
死鎖是指兩個或兩個以上的進程因競爭資源而造成的一種互相等待的現象,若無外力作用,這些進程都將無法向前推進。
飢餓:由於長期得不到想要的資源而導致進程無法向前推進的現象。如在進程調度演算法中的短進程優先演算法中,若有源源不斷的短進程到來,則長進程一直得不到處理機,從而發生了長進程飢餓。
死循環:某進程執行的過程中一直跳不出某種循環的現象。死循環可能是因為程序bug或者程序員有意為之。
(1) 互斥條件。 只有對必須互斥使用的資源爭搶(如列印機設備)才能導致死鎖。
(2) 不剝奪條件。 進程所獲得的資源在未使用完之前,不能由其他進程強行奪走,只能主動釋放。如果進程可以搶奪其他進程持有自己需要的資源的話,也就不會產生死鎖了,需要資源直接搶就行了。
(3) 請求和保持條件。 進程已經保持了至少一個資源,但是又提出了新的資源需求,而該資源又被其他進程佔有,此時請求進程被阻塞,但是又對自己持有的資源保持不放。也是很簡單的道理,如果一個進程請求的資源被阻塞,就釋放了自己持有的資源,其他進程就可以獲取它釋放的資源,也就不會發生相互等待而導致死鎖了。
(4) 循環等待條件。 存在一種進程資源的循環等待鏈,鏈中的每一個進程已經獲得的資源同時被下一個進程所請求。
(1) 對系統資源的爭搶。各進程對不可剝奪資源的競爭可能會引起死鎖。
(2) 進程推進順序非法。如果請求資源的順序不當也會導致死鎖,如上面的圖,雙方請求的資源被對方佔有而導致死鎖。
(3) 信號量的使用不當。並發執行進程時,如果信號量使用的順序不當也會到導致死鎖。
總之,對不可剝奪的資源的不合理分配,可能導致死鎖。
(1) 預防死鎖。 破壞死鎖產生的四個必要條件中的一個或幾個。
(2) 避免死鎖。 用某種方法防止系統進入安全狀態,從而避免死鎖(銀行家演算法)。
(3) 死鎖的檢測和解除。 允許死鎖的發生,不過操作系統會負責檢測出死鎖的發生,然後才去某種措施解除死鎖。
如果把只能互斥使用的資源改造成允許共享使用,則系統不會進入死鎖狀態。如 SPOOLing技術 。操作系統可以採用SPOOLing技術吧獨占設備在邏輯上改造成共享設備。 它由專門負責 I/O 的常駐內存進程以及輸入、輸出井組成。 比如,用SPOOLing技術將列印機改造為共享設備...
缺點:並不是所有的資源都可以改造成共享使用的資源。並且為了系統安全,有時候還需要保護這種互斥性。
方案一:當某個進程請求新的資源得不到滿足時,它必須立即釋放保持的所有資源,待以後需要時重新申請。
方案二:申請的資源被其他進程佔用時,藉助操作系統的協助,剝奪進程資源,至於剝奪哪個進程資源可以根據優先順序考慮。
缺點:實現復雜。暫時請求不到某個資源,之前獲取的資源就需要釋放,以後重新申請,如果一直這樣可能會導致飢餓。
可以採用 靜態分配方法 ,即進程在運行前一次申請完它所需要的全部資源,在它的資源未滿足之前,不讓它運行。一旦運行,這些資源在運行期間一直歸它所有,該進程就不會再請求別的任何資源。
缺點:如果有些資源只需要用很短的時間,因此如果進程運行時間長,在運行期間都會保持持有所有資源,就會造成資源浪費, 資源利用率低。 此外,該策略可能導致某些進程飢餓。如下,如果C類進程需要資源1和資源2,如果有大量的A或B類進程,就會導致C類進程一直不能一次獲取全部需要的資源,導致飢餓。
可採用 順序資源分配法。 首先給系統中的資源編號,規定每個進程必須按編號遞增的順序請求資源,同類資源一次申請完。
原理:一個進程只要已佔有我號的資源時,才有資格申請更大號編號的資源。按照這樣的規則,已持有大編號的資源就不會逆向回來申請我號的資源,從而就不會產生循環等待的現象。
缺點:
(1) 實現復雜。
(2) 不方便增加新的設備,因為要重新分配所有編號。
(3) 進程實際使用資源的順序可能和資源編號遞增順序不一致,會導致資源浪費。例如列印機設備編號2,輸出設備編號為1,那麼一個進程請求列印機設備前,必須先請求輸出設備,而輸出設備在請求列印機設備這一段時間內根本沒有發揮作用,其他進程也不能訪問,造成資源浪費。
假如你是一個成功的銀行家,手裡有100個小目標資金....現在有三家公司A、B、C分別向從你貸款
然而,有個規則,如果借給企業的錢達不到企業提出的最大需求,那麼錢可能就一去不復返了.....
剛開始,三家公司分別從你這里借了20、10、30億.......
此時,手裡還要40億,此時B表示還要借20億,那麼你需要考慮可以借嗎?
如果給B借了20億.....此時手裡還要有20億。
之後看手裡剩下的錢能不能周轉過來,現在可以將剩下的20億借給C,C就達到了最大需求,之後C還錢50億,然後借給A,A達到最大需求,最後A還70億,最後A........還好借給B20億後,可以通過 C->A->B 這個順序周轉,所以這20億可以借。
現在看另一種情況,回到最初狀態,現在手裡還有40億
對於上面的第一種借給B20億是安全的,因為會存在C->A->B這樣的周轉路徑(安全序列),不會血本無歸。
安全序列:如果系統按照這種序列分配資源,則每個進程都能順利完成。 只要能找出一個安全序列,系統就是 安全的 。一個系統的 安全序列可能有多個 。
如果分配了資源之後,系統中找不到任何一個安全序列,系統進入了 不安全狀態 ,這就意味著之後可能所有的進程都無法順序執行下去。當然,如果有進程提前歸還了一些資源(如對上面的第二中情況,如果B提前還10億,那麼就可以周轉了....),那系統也可能 重新回到安全狀態 ,不過在分配資源之前總是考慮最壞情況 。
如果系統處於 安全狀態 ,就 一定不會發生死鎖 。如果系統進入了不安全狀態未必一定發生死鎖,但是發生了死鎖一定是在不安全狀態。
銀行家演算法 核心思想: 在進程提出資源請求時,先預先判斷此次分配是否會導致系統進入不安全狀態,如果進入不安全狀態,就暫時不答應這次請求,讓該進程先阻塞。
銀行家演算法步驟:
如果系統中既不採取預防死鎖的措施,也不採取避免死鎖的措施,系統就很可能發生死鎖。在這種情況下,系統應當提供兩個演算法:
(1) 死鎖檢測演算法:用於檢測系統狀態,以確定系統中是否發生了死鎖。
(2) 死鎖解除演算法:當認定系統中已經發生了死鎖,利用該演算法可將系統從死鎖狀態中解脫出來。
系統死鎖可利用 資源分配圖 來描述。
上圖可以看到,R1類資源的資源數已經全部分配完了,R2類資源還有一個資源。P1進程向R2類資源請求一個資源,P2進程向R1類資源請求一個資源。
如果系統中剩餘可用的資源數足夠滿足進程的需求,那麼這個進程暫時是不會阻塞的,可以順利的執行下去。如果這個進程執行結束了把資源歸還給系統,就可能使某些正在等待的資源的進程重新被激活,並順利的執行下去。相應的,這些被激活的進程執行完後又會歸還一些資源,這樣可能又會激活另外一些阻塞的進程...
按照上面的過程分析,最終 能消除所有邊 ,就稱這個圖是 可完全簡化的 。此時一定 沒有發生死鎖 (相當於找到一個安全序列)。如果最終 不能消除所有邊 ,那麼此時就是 發生死鎖了。
最終還連著邊的進程就是處於死鎖狀態的進程。
檢測死鎖的演算法:
死鎖定理:如果某時刻系統的資源分配圖是不可完全簡化的,那麼此時系統死鎖。
下圖是一個系統死鎖的圖:
即使P3釋放了資源,P1和P2進程都不滿足繼續運行的條件,所以此時P1和P2就是死鎖進程。
解除死鎖的方法有:
(1) 資源剝奪法。 掛起(暫時放在外存上)某些死鎖進程,並搶占它的資源,將這些資源分配給其他進程,但是應防止被掛起長時間導致飢餓。
(2) 撤銷進程法。 強制撤銷部分、甚至全部死鎖進程,並剝奪這些進程的資源。這中方法實現簡單,但是也是有代價的,如果有些已經運行了很長時間了,離成功只有一步之遙了,此時撤銷導致功虧一簣,還需要從頭再來....
(3) 進程回退法。 讓一個或多個死鎖進程回退到足以避免死鎖的地步。這就要求系統要記錄進程的歷史信息,設置還原點。
那麼對哪些進程動手呢?可以考慮優先對以下的進程處理:
(1) 優先順序低的進程。
(2) 執行時間段的進程。
(3) 距離運行結束剩餘時間長的進程。
(4) 使用資源多的進程。
(5) 批處理式而不是互動式的進程。
2. 避免死鎖的方法有哪些
1、避免給一個鎖嵌套上鎖,在持有一個鎖的時候,不要再給這個鎖上鎖。如果使用多個鎖,使用std::lock。
2、在持有鎖時,不要調用別人提供的函數,因為你不清楚別人的代碼怎麼實現的,不知道它是不是在使用鎖。
3、給多個鎖上鎖時,固定順序。如果在給多個所上鎖,並且無法使用std::lock,最好的做法就是在每一個線程中,都按照同樣的順序。
4、分層次來使用鎖,把程序分成幾個層次。區分每個層次中使用的鎖,當一個線程已經持有更低層次的鎖時,不允許使用高層次的鎖。可以在程序運行時給不同的鎖加上層次號,記錄每個線程持有的鎖。
(2)線程死鎖解決方法擴展閱讀:
解決方法
在系統中已經出現死鎖後,應該及時檢測到死鎖的發生,並採取適當的措施來解除死鎖。
死鎖預防。
這是一種較簡單和直觀的事先預防的方法。方法是通過設置某些限制條件,去破壞產生死鎖的四個必要條件中的一個或者幾個,來預防發生死鎖。預防死鎖是一種較易實現的方法,已被廣泛使用。但是由於所施加的限制條件往往太嚴格,可能會導致系統資源利用率和系統吞吐量降低。
死鎖避免。
系統對進程發出的每一個系統能夠滿足的資源申請進行動態檢查,並根據檢查結果決定是否分配資源;如果分配後系統可能發生死鎖,則不予分配,否則予以分配。這是一種保證系統不進入死鎖狀態的動態策略。
死鎖檢測和解除。
先檢測:這種方法並不須事先採取任何限制性措施,也不必檢查系統是否已經進入不安全區,此方法允許系統在運行過程中發生死鎖。但可通過系統所設置的檢測機構,及時地檢測出死鎖的發生,並精確地確定與死鎖有關的進程和資源。檢測方法包括定時檢測、效率低時檢測、進程等待時檢測等。
然後解除死鎖:採取適當措施,從系統中將已發生的死鎖清除掉。
這是與檢測死鎖相配套的一種措施。當檢測到系統中已發生死鎖時,須將進程從死鎖狀態中解脫出來。常用的實施方法是撤銷或掛起一些進程,以便回收一些資源,再將這些資源分配給已處於阻塞狀態的進程,使之轉為就緒狀態,以繼續運行。死鎖的檢測和解除措施,有可能使系統獲得較好的資源利用率和吞吐量,但在實現上難度也最大。
3. 解決死鎖的4種基本方法(值得收藏)
解決死鎖的4種基本方法(文末有驚喜)
1、預防死鎖:通過設置一些限制條件,去破壞產生死鎖的必要條件
2、避免死鎖:在資源分配過程中,使用某種方法避免系統進入不安全的狀態,從而避免發生死鎖
3、檢測死鎖:允許死鎖的發生,但是通過系統的檢測之後,採取一些措施,將死鎖清除掉
4、解除死鎖:該方法與檢測死鎖配合使用
死鎖介紹
死鎖是指兩個或兩個以上的進程在執行過程中,由於競爭資源或者由於彼此通信而造成的一種阻塞的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的進程稱為死鎖進程。
產生條件
雖然進程在運行過程中,可能發生死鎖,但死鎖的發生也必須具備一定的條件,死鎖的發生必須具備以下四個必要條件。
1)互斥條件:指進程對所分配到的資源進行排它性使用,即在一段時間內某資源只由一個進程佔用。如果此時還有其它進程請求資源,則請求者只能等待,直至佔有資源的進程用畢釋放。
2)請求和保持條件:指進程已經保持至少一個資源,但又提出了新的資源請求,而該資源已被其它進程佔有,此時請求進程阻塞,但又對自己已獲得的其它資源保持不放。
3)不剝奪條件:指進程已獲得的資源,在未使用完之前,不能被剝奪,只能在使用完時由自己釋放。
4)環路等待條件:指在發生死鎖時,必然存在一個進程——資源的環形鏈,即進程集合{P0,P1,P2,···,Pn}中的P0正在等待一個P1佔用的資源;P1正在等待P2佔用的資源,……,Pn正在等待已被P0佔用的資源。
小關注來一波,我為你們准備了最新java學習資料文檔以及高清視頻教程,有需要的小夥伴掃一掃更直接
4. countdownlatch 導致的多線程死鎖
countdownlatch是通過計數器實現的,初始化時定義count數,每一個線程執行完將count數-1.當count=0時表示所以線程執行完畢,可以進入接下來的邏輯。
countdownlatch的await()方法是等待count=0,執行此方法時,執行完的線程會進入阻塞,並等待其他線程完成,當所有線程完成時,await會喚醒阻塞隊列並釋放所有線程資源。
當高並發請求時,countdownlatch的await方法有可能會引起死鎖。如果使用的線程池數量較少,在高並發時會出現多個請求佔用了全部的線程資源,但是每個請求又需要await其他線程,其他線程在等待線程池資源,導致多個請求同時進入線程阻塞,最後形成死鎖。
解決方法,使用自定義線程池,擴大線程數量,並且建立線程池拒絕機制。
5. 死鎖的原因及解決方法 死鎖的原因及解決辦法
1、死鎖是由於兩個或以上的線程互相持有對方需要的資源,導致這些線程處於等待狀態,無法執行。
2、產生死鎖的四個必要條件互斥性:線程對資源的佔有是排他性的,一個資源只能被一個線程佔有,直到釋放。請求和保持條件:一個線程對請求被佔有資源發生阻塞時,對已經獲得的資源不釋放。不剝奪:一個線程在釋放資源之前,其他的線程無法剝奪佔用。循環等待:發生死鎖時,線程進入死循環,永久阻塞。
3、產生死鎖的原因競爭不可搶占性資源,p1已經打開F1,想去打開F2,p2已經打開F2,想去打開F1,但是F1和F2都是不可搶占的,這是發生死鎖。
4、競爭可消耗資源引起死鎖,進程間通信,如果順序不當,會產生死鎖,比如p1發消息m1給p2,p1接收p3的消息m3,p2接收p1的m1,發m2給p3,p3,以此類推,如果進程之間是先發信息的那麼可以完成通信,但是如果是先接收信息就會產生死鎖。
5、進程推進順序不當,進程在運行過程中,請求和釋放資源的順序不當,也同樣會導致產生進程死鎖。
6、避免死鎖的方法破壞「請求和保持」條件想辦法,讓進程不要那麼貪心,自己已經有了資源就不要去競爭那些不可搶占的資源。比如,讓進程在申請資源時,一次性申請所有需要用到的資源,不要一次一次來申請,當申請的資源有一些沒空,那就讓線程等待。不過這個方法比較浪費資源,進程可能經常處於飢餓狀態。還有一種方法是,要求進程在申請資源前,要釋放自己擁有的資源。
7、破壞「不可搶占」條件,允許進程進行搶占,方法一:如果去搶資源,被拒絕,就釋放自己的資源。方法二:操作系統允許搶,只要你優先順序大,可以搶到。
8、破壞「循環等待」條件將系統中的所有資源統一編號,進程可在任何時刻提出資源申請,但所有申請必須按照資源的編號順序(升序)提出
9、死鎖的檢測每個進程、每個資源制定唯一編號。設定一張資源分配表,記錄各進程與佔用資源之間的關系。設置一張進程等待表,記錄各進程與要申請資源之間的關系。
10、死鎖的解除搶占資源,從一個或多個進程中搶占足夠數量的資源,分配給死鎖進程,以解除死鎖狀態。
11、終止(或撤銷)進程,終止(或撤銷)系統中的一個或多個死鎖進程,直至打破循環環路,使系統從死鎖狀態解脫出來.
6. 解決死鎖的4種基本方法
解決死鎖的4種基本方法:
1、預防死鎖:通過設置一些限制條件,去破壞產生死鎖的必要條件。
2、避免死鎖:在資源分配過程中,使用某種方法避免系統進入不安全的狀態,從而避免發生死鎖。
3、檢測死鎖:允許死鎖的發生,但是通過系統的檢測之後,採取一些措施,將死鎖清除掉。
4、解除死鎖:該方法與檢測死鎖配合使用。
產生條件
進程在運行過程中,可能發生死鎖,但死鎖的發生也必須具備一定的條件,死鎖的發生必須具備以下四個必要條件。
1)互斥條件:指進程對所分配到的資源進行排它性使用,即在一段時間內某資源只由一個進程佔用。如果此時還有其它進程請求資源,則請求者只能等待,直至佔有資源的進程用畢釋放。
2)請求和保持條件:指進程已經保持至少一個資源,但又提出了新的資源請求,而該資源已被其它進程佔有,此時請求進程阻塞,但又對自己已獲得的其它資源保持不放。
3)不剝奪條件:指進程已獲得的資源,在未使用完之前,不能被剝奪,只能在使用完時由自己釋放。
4)環路等待條件:指在發生死鎖時,必然存在一個進程——資源的環形鏈,即進程集合{P0,P1,P2,···,Pn}中的P0正在等待一個P1佔用的資源;P1正在等待P2佔用的資源,……,Pn正在等待已被P0佔用的資源。
7. 死鎖怎麼解決
處理死鎖的思路如下:
預防死鎖:破壞四個必要條件中的一個或多個來預防死鎖。
避免死鎖:在資源動態分配的過程中,用某種方式防止系統進入不安全的狀態。
檢測死鎖:運行時產生死鎖,及時發現思索,將程序解脫出來。
解除死鎖:發生死鎖後,撤銷進程,回收資源,分配給正在阻塞狀態的進程。
預防死鎖的辦法:
破壞請求和保持條件:
1、一次性的申請所有資源。之後不在申請資源,如果不滿足資源條件則得不到資源分配。
2、只獲得初期資源運行,之後將運行完的資源釋放,請求新的資源。
破壞不可搶占條件:當一個進程獲得某種不可搶占資源,提出新的資源申請,若不能滿足,則釋放所有資源,以後需要,再次重新申請。
破壞循環等待條件:對資源進行排號,按照序號遞增的順序請求資源。若進程獲得序號高的資源想要獲取序號低的資源,就需要先釋放序號高的資源。
(7)線程死鎖解決方法擴展閱讀
形成死鎖的四個必要條件:
(1) 互斥條件:一個資源每次只能被一個進程使用。
(2) 請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
(3) 不剝奪條件:進程已獲得的資源,在末使用完之前,不能強行剝奪。
(4) 循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關系。
如果一組進程中每一個進程都在等待僅由該組進程中的其他進程才能引發的事件,那麼該組進程是死鎖的。
舉例來說:有兩個進程A和B,A持有資源a等待b資源,B持有資源b等待a資源,兩個進程都在等待另一個資源的同時不釋放資源,就形成死鎖。
8. 產生線程死鎖的原因和處理方式
線程同步(就是加鎖)會有一個問題,就是產生死鎖
所謂死鎖: 是指兩個或兩個以上的進程在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。
地上放著兩個桶泡麵,一個老壇酸菜,一個小雞燉磨茹。有兩個人: 一個產品 (線程1), 一個測試 (線程2),同時撲向 搶老壇酸菜 (鎖A)和 小雞燉磨茹 (鎖B),產品拿到老壇酸菜,測試拿到小雞燉磨茹,同一時刻,產品伸要去拽測試懷里的小雞燉磨茹,測試伸手去拽產品的老壇酸菜,互使剪刀腳兩個僵持不下,就卡死在那了,叫這就死鎖。如果沒有 一個開發 將他們各打一頓解救出來(中斷狀態),它們將無法推進下去。
死鎖是因為多線程訪問共享資源,由於訪問的順序不當所造成的,通常是一個線程鎖定了一個資源A,而又想去鎖定資源B;在另一個線程中,鎖定了資源B,而又想去鎖定資源A以完成自身的操作,兩個線程都想得到對方的資源,而不願釋放自己的資源,造成兩個線程都在等待,而無法執行的情況。
如果只使用一個鎖就不會有死鎖的問題,不過復雜場景下不太理實。
1.以確定的順序獲得鎖
2.超時放棄
Lock介面提供了boolean tryLock(long time, TimeUnit unit) throws InterruptedException方法,該方法可以按照固定時長等待鎖,因此線程可以在獲取鎖超時以後,主動釋放之前已經獲得的所有的鎖。通過這種方式,也可以很有效地避免死鎖。
死鎖示列:
9. 怎麼解決死鎖現象
產生死鎖的原因:一是系統提供的資源數量有限,不能滿足每個進程的使用;二是多道程序運行時,進程推進順序不合理。
產生死鎖的必要條件是:1、互斥條件;2、不可剝奪條件(不可搶占);3、部分分配;4、循環等待。
根據產生死鎖的四個必要條件,只要使其中之一不能成立,死鎖就不會出現。為此,可以採取下列三種預防措施:
1、採用資源靜態分配策略,破壞"部分分配"條件;
2、允許進程剝奪使用其他進程佔有的資源,從而破壞"不可剝奪"條件;
3、採用資源有序分配法,破壞"環路"條件。
死鎖的避免不嚴格地限制死鎖的必要條件的存在,而是系統在系統運行過程中小心地避免死鎖的最終發生。最著名的死鎖避免演算法是銀行家演算法。死鎖避免演算法需要很大的系統開銷。
解決死鎖的另一條途徑是死鎖檢測方法,這種方法對資源的分配不加限制,即允許死鎖的發生。但系統定時地運行一個"死鎖檢測"程序,判斷系統是否已發生死鎖,若檢測到死鎖發生則設法加以解除。
解除死鎖常常採用下面兩種方法:1、資源剝奪法;2、撤消進程法
10. 如何避免Java線程死鎖
Java線程死鎖需要如何解決,這個問題一直在我們不斷的使用中需要只有不斷的關鍵。不幸的是,使用上鎖會帶來其他問題。讓我們來看一些常見問題以及相應的解決方法: Java線程死鎖 Java線程死鎖是一個經典的多線程問題,因為不同的線程都在等待那些根本不可能被釋放的鎖,從而導致所有的工作都無法完成。假設有兩個線程,分別代表兩個飢餓的人,他們必須共享刀叉並輪流吃飯。他們都需要獲得兩個鎖:共享刀和共享叉的鎖。 假如線程 「A」獲得了刀,而線程「B」獲得了叉。線程「A」就會進入阻塞狀態來等待獲得叉,而線程「B」則阻塞來等待「A」所擁有的刀。這只是人為設計的例子,但盡管在運行時很難探測到,這類情況卻時常發生。雖然要探測或推敲各種情況是非常困難的,但只要按照下面幾條規則去設計系統,就能夠避免Java線程死鎖問題: 讓所有的線程按照同樣的順序獲得一組鎖。這種方法消除了 X 和 Y 的擁有者分別等待對方的資源的問題。 將多個鎖組成一組並放到同一個鎖下。前面Java線程死鎖的例子中,可以創建一個銀器對象的鎖。於是在獲得刀或叉之前都必須獲得這個銀器的鎖。 將那些不會阻塞的可獲得資源用變數標志出來。當某個線程獲得銀器對象的鎖時,就可以通過檢查變數來判斷是否整個銀器集合中的對象鎖都可獲得。如果是,它就可以獲得相關的鎖,否則,就要釋放掉銀器這個鎖並稍後再嘗試。 最重要的是,在編寫代碼前認真仔細地設計整個系統。多線程是困難的,在開始編程之前詳細設計系統能夠幫助你避免難以發現Java線程死鎖的問題。 Volatile 變數,volatile 關鍵字是 Java 語言為優化編譯器設計的。以下面的代碼為例: 1.class VolatileTest {
2.public void foo() {
3.boolean flag = false;
4.if(flag) {
5.//this could happen
6.}
7.}
8.} 一個優化的編譯器可能會判斷出if部分的語句永遠不會被執行,就根本不會編譯這部分的代碼。如果這個類被多線程訪問, flag被前面某個線程設置之後,在它被if語句測試之前,可以被其他線程重新設置。用volatile關鍵字來聲明變數,就可以告訴編譯器在編譯的時候,不需要通過預測變數值來優化這部分的代碼。 無法訪問的Java線程死鎖有時候雖然獲取對象鎖沒有問題,線程依然有可能進入阻塞狀態。在 Java 編程中IO就是這類問題最好的例子。當線程因為對象內的IO調用而阻塞時,此對象應當仍能被其他線程訪問。該對象通常有責任取消這個阻塞的IO操作。造成阻塞調用的線程常常會令同步任務失敗。如果該對象的其他方法也是同步的,當線程被阻塞時,此對象也就相當於被冷凍住了。 其他的線程由於不能獲得對象的Java線程死鎖,就不能給此對象發消息(例如,取消 IO 操作)。必須確保不在同步代碼中包含那些阻塞調用,或確認在一個用同步阻塞代碼的對象中存在非同步方法。盡管這種方法需要花費一些注意力來保證結果代碼安全運行,但它允許在擁有對象的線程發生阻塞後,該對象仍能夠響應其他線程。 編輯推薦: 1. Java多線程優化之偏向鎖原理分析 2. Java多線程實現非同步調用的方法 3. 使用Java多線程機制實現下載的方法介紹