死锁的四个条件:
1. 互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
2. 不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占用者主动释放
3. 请求和保持,即当资源的请求者在请求其他的资源的同时保持对原有资源的占有
4. 循环等待,即存在一个等待队列: P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。
当上述四个条件都成立,便形成死锁。
/**
* Java 程序通过强制循环等待来创建死锁。
*/
public class DeadLockDemo {
/*
* 此方法请求两个锁,第一个字符串,然后整数
*/
public void method1() {
synchronized (String.class) {
System.out.println("Aquired lock on String.class object");
synchronized (Integer.class) {
System.out.println("Aquired lock on Integer.class object");
}
}
}
/*
* 此方法也请求相同的两个锁,但完全
* 相反的顺序,即首先整数,然后字符串。
* 如果一个线程持有字符串锁,则这会产生潜在的死锁
* 和其他持有整数锁,他们等待对方,永远。
*/
public void method2() {
synchronized (Integer.class) {
System.out.println("Aquired lock on Integer.class object");
synchronized (String.class) {
System.out.println("Aquired lock on String.class object");
}
}
}
}
如果仔细查看了上面的代码,可以发现死锁的真正原因不是多个线程, 而是它们请求锁的方式, 如果能提供有序访问, 则问题将得到解决。