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

