MST
星途 面试题库

面试题:并发与同步:死锁产生的四个必要条件及简单场景分析

请阐述死锁产生的四个必要条件,并举例说明在一个简单的多线程程序场景中,如何因满足这四个条件而导致死锁。
24.4万 热度难度
操作系统并发与同步

知识考点

AI 面试

面试题答案

一键面试

死锁产生的四个必要条件

  1. 互斥条件:资源在某一时刻只能被一个线程所占有,其他线程若要使用该资源,需等待资源被释放。例如,打印机在同一时间只能为一个任务进行打印工作。
  2. 占有并等待条件:线程已经持有了至少一个资源,但又提出了新的资源请求,而该新资源被其他线程占有,此时请求线程会等待新资源,同时不会释放已持有的资源。比如,一个人在吃饭时,一只手拿着筷子(已占有资源),又想拿勺子(请求新资源),在拿到勺子前不会放下筷子。
  3. 不可剥夺条件:线程所获得的资源在未使用完毕之前,不能被其他线程强行夺走,只能由获得该资源的线程自己释放。例如,进程已经获取了打印机资源,在打印任务完成前,其他进程不能强制拿走打印机资源。
  4. 循环等待条件:存在一个线程 - 资源的循环链,链中每个线程都在等待下一个线程所占用的资源。比如,线程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多线程程序中:

  • 互斥条件resource1resource2都是互斥资源,同一时间只能被一个线程占有。
  • 占有并等待条件thread1先占有resource1,然后等待resource2thread2先占有resource2,然后等待resource1
  • 不可剥夺条件thread1获得resource1后,thread2不能强行剥夺;同理thread2获得resource2后,thread1也不能强行剥夺。
  • 循环等待条件thread1等待thread2持有的resource2thread2等待thread1持有的resource1,形成了循环等待。最终导致死锁。