Java中的死锁

Java中的死锁是多线程的一部分。当一个线程等待另一个线程已经获得的对象锁,并且第二个线程等待一个被第一个线程已经获得的对象锁时,就会发生死锁。由于两个线程都在等待对方释放锁,所以这种情况被称为死锁。

java-deadlock.png

Java中死锁的示例

TestDeadlockExample1.java

public class TestDeadlockExample1 {  
  public static void main(String[] args) {  
    final String resource1 = "ratan jaiswal";  
    final String resource2 = "vimal jaiswal";  
    // t1 尝试锁定资源 1,然后锁定资源 2 
    Thread t1 = new Thread() {  
      public void run() {  
          synchronized (resource1) {  
           System.out.println("Thread 1: locked resource 1");  
  
           try { Thread.sleep(100);} catch (Exception e) {}  
  
           synchronized (resource2) {  
            System.out.println("Thread 1: locked resource 2");  
           }  
         }  
      }  
    };  
  
    // t2 尝试锁定 resource2 然后 resource1  
    Thread t2 = new Thread() {  
      public void run() {  
        synchronized (resource2) {  
          System.out.println("Thread 2: locked resource 2");  
  
          try { Thread.sleep(100);} catch (Exception e) {}  
  
          synchronized (resource1) {  
            System.out.println("Thread 2: locked resource 1");  
          }  
        }  
      }  
    };  
  
      
    t1.start();  
    t2.start();  
  }  
}       

输出:

Thread 1: locked resource 1
        Thread 2: locked resource 2

更复杂的死锁

死锁可能涉及多于两个线程。原因是很难检测到死锁。以下是一个涉及四个线程的示例:

线程1锁定A,等待B

线程2锁定B,等待C

线程3锁定C,等待D

线程4锁定D,等待A

线程1等待线程2,线程2等待线程3,线程3等待线程4,线程4等待线程1。

如何避免死锁?

解决问题的方法在于解决其根源。在死锁中,访问资源A和B的模式是主要问题。为了解决此问题,我们只需要重新排列代码访问共享资源的语句即可。

DeadlockSolved.java

public class DeadlockSolved {  
   
    public static void main(String ar[]) {  
        DeadlockSolved test = new DeadlockSolved();  
   
        final resource1 a = test.new resource1();  
        final resource2 b = test.new resource2();  
   
   //线程 1    
Runnable b1 = new Runnable() {  
    public void run() {  
        synchronized (b) {  
            try {  
                /*  添加延迟以便两个线程都可以开始尝试锁定资源 */  
                Thread.sleep(100);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
            // Thread-1 有 resource1 但也需要 resource2
            synchronized (a) {  
                System.out.println("In block 1");  
            }  
        }  
    }  
};  
   
// 线程 2   
Runnable b2 = new Runnable() {  
    public void run() {  
        synchronized (b) {  
            // Thread-2 有 resource2 但也需要 resource1
            synchronized (a) {  
                System.out.println("In block 2");  
            }  
        }  
    }  
};  
  
   
        new Thread(b1).start();  
        new Thread(b2).start();  
    }  
   
    // 资源1   
    private class resource1 {  
        private int i = 10;  
   
        public int getI() {  
            return i;  
        }  
   
        public void setI(int i) {  
            this.i = i;  
        }  
    }  
   
    // 资源2   
    private class resource2 {  
        private int i = 20;  
   
        public int getI() {  
            return i;  
        }  
   
        public void setI(int i) {  
            this.i = i;  
        }  
    }  
}  

输出:

In block 1
In block 2

在上面的代码中,DeadlockSolved类解决了死锁的情况。它有助于避免死锁,并在遇到死锁时解决它们。

如何避免Java中的死锁?

死锁无法完全解决。但是我们可以通过遵循下面提到的基本规则来避免死锁:

  1. 避免嵌套锁:我们必须避免给多个线程提供锁,这是死锁条件的主要原因。通常情况下,当你给多个线程提供锁时,这种情况就会发生。
  2. 避免不必要的锁:锁应该只给重要的线程。给不必要的线程提供锁会导致死锁条件。
  3. 使用线程的Join方法:死锁通常发生在一个线程等待另一个线程完成的情况下。在这种情况下,我们可以使用join方法,并设置一个最大时间,表示线程将花费的最长时间。

标签: java, Java面试题, Java下载, java教程, java技术, Java学习, Java学习教程, Java语言, Java开发, Java入门教程, Java进阶教程, Java高级教程, Java笔试题, Java编程思想