如何在 Java 中避免死锁?


在 Java 中,死锁是一种编程情况,在这种情况下,两个或更多个线程永久被阻塞。死锁条件将出现在至少两个线程和两个或更多个资源中。

如何避免死锁

  • 避免嵌套锁 − 死锁主要发生在我们向多个线程提供锁的时候。如果我们已经向一个线程提供了锁,则避免向多个线程提供锁。

  • 避免不必要的锁 − 我们只能锁住那些必需的成员。不必要地锁住可能会导致死锁。

  • 使用 Thread.join() − 当一个线程等待另一个线程完成时,死锁条件就会出现。如果出现此条件,我们可以在执行将花费的最长时间内使用 Thread.join()。

示例

public class DeadlockTest {
   public static void main(String[] args) throws InterruptedException {
      Object obj1 = new Object();
      Object obj2 = new Object();
      Object obj3 = new Object();
      Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1");
      Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2");
      t1.start();
      Thread.sleep(2000);
      t2.start();
      Thread.sleep(2000);
   }
}
class SyncThread implements Runnable {
   private Object obj1;
   private Object obj2;
   public SyncThread(Object o1, Object o2){
      this.obj1=o1;
      this.obj2=o2;
   }
   @Override
   public void run() {
      String name = Thread.currentThread().getName();
      System.out.println(name + " acquiring lock on " + obj1);
      synchronized (obj1) {
         System.out.println(name + " acquired lock on " + obj1);
         work();
      }
      System.out.println(name + " released lock on " + obj1);
      System.out.println(name + " acquiring lock on " + obj2);
      synchronized (obj2) {
         System.out.println(name + " acquired lock on " + obj2);
         work();
      }
      System.out.println(name + " released lock on " + obj2);
      System.out.println(name + " finished execution.");
   }
   private void work() {
      try {
         Thread.sleep(5000);
      } catch (InterruptedException ie) {
         ie.printStackTrace();
      }
   }
}

输出

t1 acquiring lock on java.lang.Object@27a54c50
t1 acquired lock on java.lang.Object@27a54c50
t2 acquiring lock on java.lang.Object@2ee6a5aa
t2 acquired lock on java.lang.Object@2ee6a5aa
t1 released lock on java.lang.Object@27a54c50
t1 acquiring lock on java.lang.Object@2ee6a5aa
t2 released lock on java.lang.Object@2ee6a5aa
t2 acquiring lock on java.lang.Object@20214e06
t1 acquired lock on java.lang.Object@2ee6a5aa
t2 acquired lock on java.lang.Object@20214e06
t1 released lock on java.lang.Object@2ee6a5aa
t2 released lock on java.lang.Object@20214e06
t1 finished execution.
t2 finished execution.

更新时间: 2023 年 11 月 24 日

5000 多次浏览

开启你的职业生涯

通过完成课程获得认证

开始
广告