以下是一个经典的死锁示例,通过两个线程互相持有对方需要的锁资源,导致程序无法继续执行:

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(100);
                } catch (InterruptedException e) {}
                System.out.println("Thread 1: Waiting for lock 2...");
                synchronized (lock2) {
                    System.out.println("Thread 1: Acquired lock 2!");
                }
            }
        });

        Thread thread2 = new Thread(() -> {
            synchronized (lock2) {
                System.out.println("Thread 2: Holding lock 2...");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {}
                System.out.println("Thread 2: Waiting for lock 1...");
                synchronized (lock1) {
                    System.out.println("Thread 2: Acquired lock 1!");
                }
            }
        });

        thread1.start();
        thread2.start();
    }
}

死锁产生条件

这段代码满足了死锁产生的四个必要条件:

  • 互斥条件:锁资源一次只能被一个线程持有
  • 持有并等待:线程持有锁1的同时等待锁2
  • 非抢占条件:已获得的锁不能被其他线程强制夺取
  • 循环等待条件:线程1等待线程2释放锁,线程2等待线程1释放锁

运行结果观察

执行这段代码时,程序会输出前几条信息后卡住,无法继续执行:

Thread 1: Holding lock 1...
Thread 2: Holding lock 2...
Thread 1: Waiting for lock 2...
Thread 2: Waiting for lock 1...

避免死锁的方法

在实际开发中可以通过以下方式避免死锁:

  • 按固定顺序获取锁资源
  • 使用锁超时机制(如tryLock)
  • 减少锁的作用域范围
  • 使用更高级的并发工具代替显式锁
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐