Java并发编程学习十二:死锁问题
一、死锁的产生
想要产生死锁,必须同时满足4个必要条件:
- 互斥条件:每个资源每次只能被一个线程(或进程,下同)使用。否则,如果每个人都可以拿到想要的资源,那就不需要等待,所以是不可能发生死锁的
- 请求保持条件:当一个线程因请求资源而阻塞时,则需对已获得的资源保持不放。否则,在请求资源时阻塞后自动释放手中 资源(例如锁)的话,其他线程获取到其他的资源,就不会形成死锁
- 不剥夺条件:线程已获得的资源,在未使用完之前,不会被强行剥夺。否则,其他线程可以强行获取资源,同样不会形成死锁
- 循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系时,才有可能形成死锁。如两个线程互相持有对方所需要的资源,三个及以上的线程形成环路,依次请求下一个线程已经持有的资源
下面是一个必然会发生死锁的案例:
/**
* 描述: 必定死锁的情况
*/
public class MustDeadLock implements Runnable {
public int flag;
static Object o1 = new Object();
static Object o2 = new Object();
public void run() {
System.out.println("线程"+Thread.currentThread().getName() + "的flag为" + flag);
if (flag == 1) {
synchronized (o1) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (o2) {
System.out.println("线程1获得了两把锁");
}
}
}
if (flag == 2) {
synchronized (o2) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (o1) {
System.out.println("线程2获得了两把锁");
}
}
}
}
public static void main(String[] argv) {
MustDeadLock r1 = new MustDeadLock();
MustDeadLock r2 = new MustDeadLock();
r1.flag = 1;
r2.flag = 2;
Thread t1 = new Thread(r1, "t1");
Thread t2 = new Thread(r2, "t2");
t1.start();
t2.start();
}
}