詳解Java的線程的優(yōu)先級(jí)以及死鎖
Java線程優(yōu)先級(jí)
需要避免的與多任務(wù)處理有關(guān)的特殊錯(cuò)誤類型是死鎖(deadlock)。死鎖發(fā)生在當(dāng)兩個(gè)線程對(duì)一對(duì)同步對(duì)象有循環(huán)依賴關(guān)系時(shí)。例如,假定一個(gè)線程進(jìn)入了對(duì)象X的管程而另一個(gè)線程進(jìn)入了對(duì)象Y的管程。如果X的線程試圖調(diào)用Y的同步方法,它將像預(yù)料的一樣被鎖定。而Y的線程同樣希望調(diào)用X的一些同步方法,線程永遠(yuǎn)等待,因?yàn)闉榈竭_(dá)X,必須釋放自己的Y的鎖定以使第一個(gè)線程可以完成。死鎖是很難調(diào)試的錯(cuò)誤,因?yàn)椋?br />
通常,它極少發(fā)生,只有到兩線程的時(shí)間段剛好符合時(shí)才能發(fā)生。
它可能包含多于兩個(gè)的線程和同步對(duì)象(也就是說,死鎖在比剛講述的例子有更多復(fù)雜的事件序列的時(shí)候可以發(fā)生)。
為充分理解死鎖,觀察它的行為是很有用的。下面的例子生成了兩個(gè)類,A和B,分別有foo( )和bar( )方法。這兩種方法在調(diào)用其他類的方法前有一個(gè)短暫的停頓。主類,名為Deadlock,創(chuàng)建了A和B的實(shí)例,然后啟動(dòng)第二個(gè)線程去設(shè)置死鎖環(huán)境。foo( )和bar( )方法使用sleep( )強(qiáng)迫死鎖現(xiàn)象發(fā)生。
// An example of deadlock. class A { synchronized void foo(B b) { String name = Thread.currentThread().getName(); System.out.println(name + " entered A.foo"); try { Thread.sleep(1000); } catch(Exception e) { System.out.println("A Interrupted"); } System.out.println(name + " trying to call B.last()"); b.last(); } synchronized void last() { System.out.println("Inside A.last"); } } class B { synchronized void bar(A a) { String name = Thread.currentThread().getName(); System.out.println(name + " entered B.bar"); try { Thread.sleep(1000); } catch(Exception e) { System.out.println("B Interrupted"); } System.out.println(name + " trying to call A.last()"); a.last(); } synchronized void last() { System.out.println("Inside A.last"); } } class Deadlock implements Runnable { A a = new A(); B b = new B(); Deadlock() { Thread.currentThread().setName("MainThread"); Thread t = new Thread(this, "RacingThread"); t.start(); a.foo(b); // get lock on a in this thread. System.out.println("Back in main thread"); } public void run() { b.bar(a); // get lock on b in other thread. System.out.println("Back in other thread"); } public static void main(String args[]) { new Deadlock(); } }
運(yùn)行程序后,輸出如下:
MainThread entered A.foo RacingThread entered B.bar MainThread trying to call B.last() RacingThread trying to call A.last()
因?yàn)槌绦蛩梨i,你需要按CTRL-C來結(jié)束程序。在PC機(jī)上按CTRL-BREAK(或在Solaris下按CTRL-\)你可以看到全線程和管程緩沖堆。你會(huì)看到RacingThread在等待管程a時(shí)占用管程b,同時(shí),MainThread占用a等待b。該程序永遠(yuǎn)都不會(huì)結(jié)束。像該例闡明的,你的多線程程序經(jīng)常被鎖定,死鎖是你首先應(yīng)檢查的問題。
Java線程死鎖
需要避免的與多任務(wù)處理有關(guān)的特殊錯(cuò)誤類型是死鎖(deadlock)。死鎖發(fā)生在當(dāng)兩個(gè)線程對(duì)一對(duì)同步對(duì)象有循環(huán)依賴關(guān)系時(shí)。例如,假定一個(gè)線程進(jìn)入了對(duì)象X的管程而另一個(gè)線程進(jìn)入了對(duì)象Y的管程。如果X的線程試圖調(diào)用Y的同步方法,它將像預(yù)料的一樣被鎖定。而Y的線程同樣希望調(diào)用X的一些同步方法,線程永遠(yuǎn)等待,因?yàn)闉榈竭_(dá)X,必須釋放自己的Y的鎖定以使第一個(gè)線程可以完成。死鎖是很難調(diào)試的錯(cuò)誤,因?yàn)椋?br />
通常,它極少發(fā)生,只有到兩線程的時(shí)間段剛好符合時(shí)才能發(fā)生。
它可能包含多于兩個(gè)的線程和同步對(duì)象(也就是說,死鎖在比剛講述的例子有更多復(fù)雜的事件序列的時(shí)候可以發(fā)生)。
為充分理解死鎖,觀察它的行為是很有用的。下面的例子生成了兩個(gè)類,A和B,分別有foo( )和bar( )方法。這兩種方法在調(diào)用其他類的方法前有一個(gè)短暫的停頓。主類,名為Deadlock,創(chuàng)建了A和B的實(shí)例,然后啟動(dòng)第二個(gè)線程去設(shè)置死鎖環(huán)境。foo( )和bar( )方法使用sleep( )強(qiáng)迫死鎖現(xiàn)象發(fā)生。
// An example of deadlock. class A { synchronized void foo(B b) { String name = Thread.currentThread().getName(); System.out.println(name + " entered A.foo"); try { Thread.sleep(1000); } catch(Exception e) { System.out.println("A Interrupted"); } System.out.println(name + " trying to call B.last()"); b.last(); } synchronized void last() { System.out.println("Inside A.last"); } } class B { synchronized void bar(A a) { String name = Thread.currentThread().getName(); System.out.println(name + " entered B.bar"); try { Thread.sleep(1000); } catch(Exception e) { System.out.println("B Interrupted"); } System.out.println(name + " trying to call A.last()"); a.last(); } synchronized void last() { System.out.println("Inside A.last"); } } class Deadlock implements Runnable { A a = new A(); B b = new B(); Deadlock() { Thread.currentThread().setName("MainThread"); Thread t = new Thread(this, "RacingThread"); t.start(); a.foo(b); // get lock on a in this thread. System.out.println("Back in main thread"); } public void run() { b.bar(a); // get lock on b in other thread. System.out.println("Back in other thread"); } public static void main(String args[]) { new Deadlock(); } }
運(yùn)行程序后,輸出如下:
MainThread entered A.foo RacingThread entered B.bar MainThread trying to call B.last() RacingThread trying to call A.last()
因?yàn)槌绦蛩梨i,你需要按CTRL-C來結(jié)束程序。在PC機(jī)上按CTRL-BREAK(或在Solaris下按CTRL-\)你可以看到全線程和管程緩沖堆。你會(huì)看到RacingThread在等待管程a時(shí)占用管程b,同時(shí),MainThread占用a等待b。該程序永遠(yuǎn)都不會(huì)結(jié)束。像該例闡明的,你的多線程程序經(jīng)常被鎖定,死鎖是你首先應(yīng)檢查的問題。
相關(guān)文章
m1 Mac設(shè)置多jdk版本并動(dòng)態(tài)切換的實(shí)現(xiàn)
本文主要介紹 Mac 下如何安裝 JDK 并且多版本如何切換,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08SpringBoot Filter修改返回內(nèi)容,解決請(qǐng)求卡死200的錯(cuò)誤
這篇文章主要介紹了SpringBoot Filter修改返回內(nèi)容,解決請(qǐng)求卡死200的錯(cuò)誤問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07Java實(shí)現(xiàn)簡(jiǎn)單雙色球搖獎(jiǎng)功能過程解析
這篇文章主要介紹了Java實(shí)現(xiàn)簡(jiǎn)單雙色球搖獎(jiǎng)功能過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09java 多態(tài)性詳解及簡(jiǎn)單實(shí)例
這篇文章主要介紹了java 多態(tài)性詳解及簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-02-02JavaWeb?使用DBUtils實(shí)現(xiàn)增刪改查方式
這篇文章主要介紹了JavaWeb?使用DBUtils實(shí)現(xiàn)增刪改查方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12IntelliJ IDEA使用快捷鍵重命名項(xiàng)目、變量、文件等方法總結(jié)
今天小編就為大家分享一篇關(guān)于IntelliJ IDEA使用快捷鍵重命名項(xiàng)目、變量、文件等方法總結(jié),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-10-10簡(jiǎn)單了解Spring中BeanFactory與FactoryBean的區(qū)別
這篇文章主要介紹了簡(jiǎn)單了解Spring中BeanFactory與FactoryBean的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12深入解析java中的靜態(tài)代理與動(dòng)態(tài)代理
本篇文章是對(duì)java中的靜態(tài)代理與動(dòng)態(tài)代理進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下,希望對(duì)大家有所幫助2013-10-10