在實際編程中狐榔,死鎖雖然不常見,但是如果遇到死鎖便是致命的收捣。接下來了解一下《操作系統(tǒng)》對于死鎖產(chǎn)生條件的描述庵楷。
死鎖產(chǎn)生的條件:
互斥條件:所謂互斥就是進(jìn)程在某一時間內(nèi)獨占資源楣颠。
請求與保持條件:一個進(jìn)程因請求資源而阻塞時童漩,對已獲得的資源保持不放春锋。
不剝奪條件:進(jìn)程已獲得資源,在末使用完之前侧馅,不能強(qiáng)行剝奪能庆。
循環(huán)等待條件:若干進(jìn)程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系。
死鎖的例子
public class Test {
public static void main(String[] args) {
DeadlockRisk dead = new DeadlockRisk();
MyThread t1 = new MyThread(dead, 1, 2);
MyThread t2 = new MyThread(dead, 3, 4);
MyThread t3 = new MyThread(dead, 5, 6);
MyThread t4 = new MyThread(dead, 7, 8);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class MyThread extends Thread {
private DeadlockRisk dead;
private int a, b;
MyThread(DeadlockRisk dead, int a, int b) {
this.dead = dead;
this.a = a;
this.b = b;
}
@Override
public void run() {
dead.read();
dead.write(a, b);
}
}
class DeadlockRisk {
private static class Resource {
public int value;
}
private Resource resourceA = new Resource();
private Resource resourceB = new Resource();
public int read() {
synchronized (resourceA) {
System.out.println("read():" + Thread.currentThread().getName() + "獲取了resourceA的鎖!");
synchronized (resourceB) {
System.out.println("read():" + Thread.currentThread().getName() + "獲取了resourceB的鎖渠旁!");
return resourceB.value + resourceA.value;
}
}
}
public void write(int a, int b) {
synchronized (resourceB) {
System.out.println("write():" + Thread.currentThread().getName() + "獲取了resourceA的鎖!");
synchronized (resourceA) {
System.out.println("write():" + Thread.currentThread().getName() + "獲取了resourceB的鎖粤铭!");
resourceA.value = a;
resourceB.value = b;
}
}
}
}
//運(yùn)行結(jié)果
read():Thread-0獲取了resourceA的鎖杂靶!
read():Thread-0獲取了resourceB的鎖!
write():Thread-0獲取了resourceA的鎖垛吗!
read():Thread-3獲取了resourceA的鎖烁登!
獲取線程dump
jps獲得當(dāng)前Java虛擬機(jī)進(jìn)程的pid
? ~ jps
657
2564 Jps
2525 AppMain
2526 Launcher-
jstack打印堆棧
Found one Java-level deadlock:
=============================
"Thread-3":
waiting to lock monitor 0x00007fd5ca80c368 (object 0x00000007d56d1550, a deadlock.DeadlockRisk$Resource),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x00007fd5ca80ed58 (object 0x00000007d56d1540, a deadlock.DeadlockRisk$Resource),
which is held by "Thread-3"Java stack information for the threads listed above: =================================================== "Thread-3": at deadlock.DeadlockRisk.read(Test.java:52) - waiting to lock <0x00000007d56d1550> (a deadlock.DeadlockRisk$Resource) - locked <0x00000007d56d1540> (a deadlock.DeadlockRisk$Resource) at deadlock.MyThread.run(Test.java:35) "Thread-0": at deadlock.DeadlockRisk.write(Test.java:62) - waiting to lock <0x00000007d56d1540> (a deadlock.DeadlockRisk$Resource) - locked <0x00000007d56d1550> (a deadlock.DeadlockRisk$Resource) at deadlock.MyThread.run(Test.java:36) Found 1 deadlock.
更多關(guān)于線程dump可以參考:http://my.oschina.net/u/161458/blog/266313
如何避免死鎖
避免一個線程同時獲取多個鎖饵沧。
避免一個線程在鎖內(nèi)同時占用多個資源,盡量保證每個鎖只占用一個資源羡儿。
嘗試使用定時鎖锁右,使用lock.tryLock(timeout)來替代使用內(nèi)部鎖機(jī)制讶泰。
對于數(shù)據(jù)庫鎖痪署,加鎖和解鎖必須在一個數(shù)據(jù)庫連接里,否則會出現(xiàn)解鎖失敗的情況狼犯。
活鎖
活鎖:馬路中間有條小橋领铐,只能容納一輛車經(jīng)過,橋兩頭開來兩輛車A和B瓢姻,A比較禮貌音诈,示意B先過,B也比較禮貌褥傍,示意A先過,結(jié)果兩人一直謙讓誰也過不去恍风。