死锁(Deadlock)是多线程并发编程中一种常见的问题,它发生在两个或多个线程互相等待对方释放资源的情况下,导致所有参与的线程都无法继续执行。
死锁通常发生在同时满足以下四个条件的情况下:
- 互斥条件(Mutual Exclusion): 一个资源每次只能被一个线程使用。
- 占有且等待(Hold and Wait): 一个线程因持有资源而等待另一个线程持有的资源。
- 非抢占条件(No Preemption): 资源不能被强行从一个线程中抢占,只能由持有它的线程自愿释放。
- 循环等待(Circular Wait): 一系列线程形成一个循环,每个线程都在等待下一个线程所持有的资源。
下面是一个简单的死锁示例:
public class DeadlockExample {
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
synchronized (lock1) {
System.out.println("Thread 1: Holding lock 1...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (lock2) {
System.out.println("Thread 1: Holding lock 1 and lock 2...");
}
}
});
Thread thread2 = new Thread(() -> {
synchronized (lock2) {
System.out.println("Thread 2: Holding lock 2...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 2: Waiting for lock 1...");
synchronized (lock1) {
System.out.println("Thread 2: Holding lock 2 and lock 1...");
}
}
});
thread1.start();
thread2.start();
}
}
在上述例子中,两个线程分别试图获取 lock1
和 lock2
,但由于它们都在持有一个锁的同时等待另一个锁,因此可能导致死锁。在实际应用中,死锁的发生是非常危险的,因为它会导致程序永远无法继续执行下去。避免死锁通常需要精心设计程序,遵循避免死锁的策略,如破坏循环等待、按序申请资源等。