死锁(Deadlock)

优质
小牛编辑
127浏览
2023-12-01

死锁描述了两个或多个线程永远被阻塞,等待彼此的情况。 当多个线程需要相同的锁但以不同的顺序获取它们时,会发生死锁。 Java多线程程序可能会遇到死锁条件,因为synchronized关键字会导致执行线程在等待与指定对象关联的锁定或监视器时阻塞。 这是一个例子。

例子 (Example)

public class TestThread {
   public static Object Lock1 = new Object();
   public static Object Lock2 = new Object();
   public static void main(String args[]) {
      ThreadDemo1 T1 = new ThreadDemo1();
      ThreadDemo2 T2 = new ThreadDemo2();
      T1.start();
      T2.start();
   }
   private static class ThreadDemo1 extends Thread {
      public void run() {
         synchronized (Lock1) {
            System.out.println("Thread 1: Holding lock 1...");
            try {
               Thread.sleep(10);
            } catch (InterruptedException e) {}
            System.out.println("Thread 1: Waiting for lock 2...");
            synchronized (Lock2) {
               System.out.println("Thread 1: Holding lock 1 & 2...");
            }
         }
      }
   }
   private static class ThreadDemo2 extends Thread {
      public void run() {
         synchronized (Lock2) {
            System.out.println("Thread 2: Holding lock 2...");
            try {
               Thread.sleep(10);
            } catch (InterruptedException e) {}
            System.out.println("Thread 2: Waiting for lock 1...");
            synchronized (Lock1) {
               System.out.println("Thread 2: Holding lock 1 & 2...");
            }
         }
      }
   } 
}

编译并执行上述程序时,会发现死锁情况,以下是程序产生的输出 -

输出 (Output)

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

上面的程序将永远挂起,因为没有任何线程可以继续并等待彼此释放锁定,因此您可以通过按CTRL + C退出程序。

死锁解决方案示例

让我们改变锁定和运行相同程序的顺序,看看两个线程是否仍然相互等待 -

例子 (Example)

public class TestThread {
   public static Object Lock1 = new Object();
   public static Object Lock2 = new Object();
   public static void main(String args[]) {
      ThreadDemo1 T1 = new ThreadDemo1();
      ThreadDemo2 T2 = new ThreadDemo2();
      T1.start();
      T2.start();
   }
   private static class ThreadDemo1 extends Thread {
      public void run() {
         synchronized (Lock1) {
            System.out.println("Thread 1: Holding lock 1...");
            try {
               Thread.sleep(10);
            } catch (InterruptedException e) {}
            System.out.println("Thread 1: Waiting for lock 2...");
            synchronized (Lock2) {
               System.out.println("Thread 1: Holding lock 1 & 2...");
            }
         }
      }
   }
   private static class ThreadDemo2 extends Thread {
      public void run() {
         synchronized (Lock1) {
            System.out.println("Thread 2: Holding lock 1...");
            try {
               Thread.sleep(10);
            } catch (InterruptedException e) {}
            System.out.println("Thread 2: Waiting for lock 2...");
            synchronized (Lock2) {
               System.out.println("Thread 2: Holding lock 1 & 2...");
            }
         }
      }
   } 
}

因此,只需更改锁的顺序就可以防止程序进入死锁情况并完成以下结果 -

输出 (Output)

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

上面的例子只是简单地概念,然而,这是一个复杂的概念,你应该在开发应用程序来处理死锁情况之前深入研究它。