程序中必须同时满足以下四个条件才会引发死锁:
互斥(Mutual exclusion):线程所使用的资源中至少有一个是不能共享的,它在同一时刻只能由一个线程使用。
持有与等待(Hold and wait):至少有一个线程已经持有了资源,并且正在等待获取其他的线程所持有的资源。
非抢占式(No pre-emption):如果一个线程已经持有了某个资源,那么在这个线程释放这个资源之前,别的线程不能把它抢夺过去使用。
循环等待(Circular wait):假设有N个线程在运行,第一个线程持有了一个资源,并且正在等待获取第二个线程持有的资源,而第二个线程正在等待获取第三个线程持有的资源,依此类推……第N个线程正在等待获取第一个线程持有的资源,由此形成一个循环等待。
举例:
1.未发生死锁
public class Test {
static Object o1 = new Object();//静态对象
static Object o2 = new Object();
public static void main(String[] args) {
synch synch1 = new synch();
synch synch2 = new synch();
synch1.a=0;
synch2.a=2;
Thread t1 = new Thread(synch1);
Thread t2 = new Thread(synch2);
t1.start();
t2.start();
}
}//Test类结束
class synch implements Runnable{
int a;
public void run() {
System.out.println(a);
if(a == 0){
try {
synchronized (Test.o1) {//对类Testt中的静态对象同步
Thread.sleep(500);
} //synchronized是对o1的对象锁,500毫秒以后会释放掉对o1的锁,所以不会发生死锁
synchronized (Test.o2) {
System.out.println("aaaa");
}
} catch (InterruptedException ex) {}
}else
try {
synchronized (Test.o2) {
Thread.sleep(500);
}
synchronized (Test.o1) {
System.out.println("aaba");
}
} catch (InterruptedException ex) {}
}
}
运行后显示
0
2
aaba
aaaa
没有发生死锁
2.发生了死锁
修改如下:
public void run() {
System.out.println(a);
if(a == 0){
try {
synchronized (Test.o1) { //已获取o1对象锁
Thread.sleep(500);
System.out.println("Try to get o2");
synchronized (Test.o2) { //未释放o1(同步块中的语句执行完以后才释放该对象的锁),尝试获取o2,被挂起
System.out.println("aaaa");
}
}
} catch (InterruptedException ex) {}
} else {
try {
synchronized (Test.o2) { //已获取o2的对象锁
Thread.sleep(500);
System.out.println("Try to get o1");
synchronized (Test.o1) { //未释放o2,尝试获取o1,也被挂起,死锁
System.out.println("aaba");
}
}
} catch (InterruptedException ex) {}
}
}
结果:
0
2
Try to get o2
Try to get o1
另一个例子:
class Friendly {
private Friendly partner;
private String name;
public Friendly(String name) {
this.name = name;
}
public synchronized void hug() {
System.out.println(Thread.currentThread().getName()+" in " + name + ".hug() trying to invoke " + partner.name +".hugBack()");
partner.hugBack();
}
private synchronized void hugBack() {
System.out.println(Thread.currentThread().getName()+" in " + name + ".hugBack()");
}
public void becomeFriend(Friendly partner) {
this.partner = partner;
}
public static void main(String[] args) {
final Friendly jareth = new Friendly("jareth");
final Friendly cory = new Friendly("cory");
jareth.becomeFriend(cory);
cory.becomeFriend(jareth);
new Thread(new Runnable() {
public void run() { jareth.hug(); }
}, "Thread1").start();
new Thread(new Runnable() {
public void run() { cory.hug(); }
}, "Thread2").start();
}
}
结果:
Thread1 in jareth.hug() trying to invoke cory.hugBack()
Thread1 in cory.hugBack()
Thread2 in cory.hug() trying to invoke jareth.hugBack()
Thread2 in jareth.hugBack()