面试题答案
一键面试死锁产生的四个必要条件
- 互斥条件:资源在某一时刻只能被一个线程所占有,其他线程若要使用该资源,需等待资源被释放。例如,打印机在同一时间只能为一个任务进行打印工作。
- 占有并等待条件:线程已经持有了至少一个资源,但又提出了新的资源请求,而该新资源被其他线程占有,此时请求线程会等待新资源,同时不会释放已持有的资源。比如,一个人在吃饭时,一只手拿着筷子(已占有资源),又想拿勺子(请求新资源),在拿到勺子前不会放下筷子。
- 不可剥夺条件:线程所获得的资源在未使用完毕之前,不能被其他线程强行夺走,只能由获得该资源的线程自己释放。例如,进程已经获取了打印机资源,在打印任务完成前,其他进程不能强制拿走打印机资源。
- 循环等待条件:存在一个线程 - 资源的循环链,链中每个线程都在等待下一个线程所占用的资源。比如,线程A等待线程B占用的资源,线程B等待线程C占用的资源,而线程C又等待线程A占用的资源。
多线程程序场景导致死锁示例
public class DeadlockExample {
private static final Object resource1 = new Object();
private static final Object resource2 = new Object();
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
synchronized (resource1) {
System.out.println("Thread 1: Holding resource 1");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (resource2) {
System.out.println("Thread 1: Holding resource 1 & 2");
}
}
});
Thread thread2 = new Thread(() -> {
synchronized (resource2) {
System.out.println("Thread 2: Holding resource 2");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (resource1) {
System.out.println("Thread 2: Holding resource 1 & 2");
}
}
});
thread1.start();
thread2.start();
}
}
在上述Java多线程程序中:
- 互斥条件:
resource1
和resource2
都是互斥资源,同一时间只能被一个线程占有。 - 占有并等待条件:
thread1
先占有resource1
,然后等待resource2
;thread2
先占有resource2
,然后等待resource1
。 - 不可剥夺条件:
thread1
获得resource1
后,thread2
不能强行剥夺;同理thread2
获得resource2
后,thread1
也不能强行剥夺。 - 循环等待条件:
thread1
等待thread2
持有的resource2
,thread2
等待thread1
持有的resource1
,形成了循环等待。最终导致死锁。