詳解Java的線(xiàn)程的優(yōu)先級(jí)以及死鎖
Java線(xiàn)程優(yōu)先級(jí)
需要避免的與多任務(wù)處理有關(guān)的特殊錯(cuò)誤類(lèi)型是死鎖(deadlock)。死鎖發(fā)生在當(dāng)兩個(gè)線(xiàn)程對(duì)一對(duì)同步對(duì)象有循環(huán)依賴(lài)關(guān)系時(shí)。例如,假定一個(gè)線(xiàn)程進(jìn)入了對(duì)象X的管程而另一個(gè)線(xiàn)程進(jìn)入了對(duì)象Y的管程。如果X的線(xiàn)程試圖調(diào)用Y的同步方法,它將像預(yù)料的一樣被鎖定。而Y的線(xiàn)程同樣希望調(diào)用X的一些同步方法,線(xiàn)程永遠(yuǎn)等待,因?yàn)闉榈竭_(dá)X,必須釋放自己的Y的鎖定以使第一個(gè)線(xiàn)程可以完成。死鎖是很難調(diào)試的錯(cuò)誤,因?yàn)椋?br />
通常,它極少發(fā)生,只有到兩線(xiàn)程的時(shí)間段剛好符合時(shí)才能發(fā)生。
它可能包含多于兩個(gè)的線(xiàn)程和同步對(duì)象(也就是說(shuō),死鎖在比剛講述的例子有更多復(fù)雜的事件序列的時(shí)候可以發(fā)生)。
為充分理解死鎖,觀(guān)察它的行為是很有用的。下面的例子生成了兩個(gè)類(lèi),A和B,分別有foo( )和bar( )方法。這兩種方法在調(diào)用其他類(lèi)的方法前有一個(gè)短暫的停頓。主類(lèi),名為Deadlock,創(chuàng)建了A和B的實(shí)例,然后啟動(dòng)第二個(gè)線(xiàn)程去設(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來(lái)結(jié)束程序。在PC機(jī)上按CTRL-BREAK(或在Solaris下按CTRL-\)你可以看到全線(xiàn)程和管程緩沖堆。你會(huì)看到RacingThread在等待管程a時(shí)占用管程b,同時(shí),MainThread占用a等待b。該程序永遠(yuǎn)都不會(huì)結(jié)束。像該例闡明的,你的多線(xiàn)程程序經(jīng)常被鎖定,死鎖是你首先應(yīng)檢查的問(wèn)題。
Java線(xiàn)程死鎖
需要避免的與多任務(wù)處理有關(guān)的特殊錯(cuò)誤類(lèi)型是死鎖(deadlock)。死鎖發(fā)生在當(dāng)兩個(gè)線(xiàn)程對(duì)一對(duì)同步對(duì)象有循環(huán)依賴(lài)關(guān)系時(shí)。例如,假定一個(gè)線(xiàn)程進(jìn)入了對(duì)象X的管程而另一個(gè)線(xiàn)程進(jìn)入了對(duì)象Y的管程。如果X的線(xiàn)程試圖調(diào)用Y的同步方法,它將像預(yù)料的一樣被鎖定。而Y的線(xiàn)程同樣希望調(diào)用X的一些同步方法,線(xiàn)程永遠(yuǎn)等待,因?yàn)闉榈竭_(dá)X,必須釋放自己的Y的鎖定以使第一個(gè)線(xiàn)程可以完成。死鎖是很難調(diào)試的錯(cuò)誤,因?yàn)椋?br />
通常,它極少發(fā)生,只有到兩線(xiàn)程的時(shí)間段剛好符合時(shí)才能發(fā)生。
它可能包含多于兩個(gè)的線(xiàn)程和同步對(duì)象(也就是說(shuō),死鎖在比剛講述的例子有更多復(fù)雜的事件序列的時(shí)候可以發(fā)生)。
為充分理解死鎖,觀(guān)察它的行為是很有用的。下面的例子生成了兩個(gè)類(lèi),A和B,分別有foo( )和bar( )方法。這兩種方法在調(diào)用其他類(lèi)的方法前有一個(gè)短暫的停頓。主類(lèi),名為Deadlock,創(chuàng)建了A和B的實(shí)例,然后啟動(dòng)第二個(gè)線(xiàn)程去設(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來(lái)結(jié)束程序。在PC機(jī)上按CTRL-BREAK(或在Solaris下按CTRL-\)你可以看到全線(xiàn)程和管程緩沖堆。你會(huì)看到RacingThread在等待管程a時(shí)占用管程b,同時(shí),MainThread占用a等待b。該程序永遠(yuǎn)都不會(huì)結(jié)束。像該例闡明的,你的多線(xiàn)程程序經(jīng)常被鎖定,死鎖是你首先應(yīng)檢查的問(wèn)題。
相關(guān)文章
一篇文章了解Jackson注解@JsonFormat及失效解決辦法
這篇文章主要給大家介紹了關(guān)于如何通過(guò)一篇文章了解Jackson注解@JsonFormat及失效解決辦法的相關(guān)資料,@JsonFormat注解是一個(gè)時(shí)間格式化注解,用于格式化時(shí)間,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11
Spring中的BeanFactory工廠(chǎng)詳細(xì)解析
這篇文章主要介紹了Spring中的BeanFactory工廠(chǎng)詳細(xì)解析,Spring的本質(zhì)是一個(gè)bean工廠(chǎng)(beanFactory)或者說(shuō)bean容器,它按照我們的要求,生產(chǎn)我們需要的各種各樣的bean,提供給我們使用,需要的朋友可以參考下2023-12-12
詳解Java的call by value和call by reference
在本篇文章里小編給大家總結(jié)了關(guān)于Java的call by value和call by reference的相關(guān)用法和知識(shí)點(diǎn)內(nèi)容,需要的朋友們學(xué)習(xí)下。2019-03-03
Java工廠(chǎng)模式用法之如何動(dòng)態(tài)選擇對(duì)象詳解
工廠(chǎng)設(shè)計(jì)模式可能是最常用的設(shè)計(jì)模式之一,我想大家在自己的項(xiàng)目中都用到過(guò)。本文不僅僅是關(guān)于工廠(chǎng)模式的基本知識(shí),更是討論如何在運(yùn)行時(shí)動(dòng)態(tài)選擇不同的方法進(jìn)行執(zhí)行,你們可以看看是不是和你們項(xiàng)目中用的一樣2023-03-03
SpringBoot Jpa企業(yè)開(kāi)發(fā)示例詳細(xì)講解
這篇文章主要介紹了SpringBoot Jpa企業(yè)開(kāi)發(fā)示例,Jpa可以通過(guò)實(shí)體類(lèi)生成數(shù)據(jù)庫(kù)的表,同時(shí)自帶很多增刪改查方法,大部分sql語(yǔ)句不需要我們自己寫(xiě),配置完成后直接調(diào)用方法即可,很方便2022-11-11
SpringBoot集成Zipkin實(shí)現(xiàn)分布式全鏈路監(jiān)控
這篇文章主要介紹了SpringBoot集成Zipkin實(shí)現(xiàn)分布式全鏈路監(jiān)控的方法啊,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09
Jmeter內(nèi)置變量vars和props的使用詳解
JMeter是一個(gè)功能強(qiáng)大的負(fù)載測(cè)試工具,它提供了許多有用的內(nèi)置變量來(lái)支持測(cè)試過(guò)程,其中最常用的變量是 vars 和 props,本文通過(guò)代碼示例詳細(xì)給大家介紹了Jmeter內(nèi)置變量vars和props的使用,需要的朋友可以參考下2024-08-08

