자바 동시성-교착 상태

교착 상태는 둘 이상의 스레드가 서로를 기다리면서 영원히 차단되는 상황을 나타냅니다. 교착 상태는 여러 스레드가 동일한 잠금을 필요로하지만 다른 순서로 획득 할 때 발생합니다. Java 다중 스레드 프로그램은 다음과 같은 이유로 교착 상태가 발생할 수 있습니다.synchronized키워드는 지정된 개체와 관련된 잠금 또는 모니터를 기다리는 동안 실행 스레드가 차단되도록합니다. 여기에 예가 있습니다.

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...");
            }
         }
      }
   } 
}

위의 프로그램을 컴파일하고 실행하면 교착 상태가 발생하고 다음은 프로그램에서 생성 된 출력입니다.

산출

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

위의 프로그램은 진행할 위치에있는 스레드 중 어느 것도 서로 잠금을 해제 할 때까지 기다리지 않기 때문에 영원히 중단됩니다. 따라서 Ctrl + C를 눌러 프로그램을 종료 할 수 있습니다.

교착 상태 솔루션 예

두 스레드가 여전히 서로를 기다리는 지 확인하기 위해 동일한 프로그램의 잠금 및 실행 순서를 변경해 보겠습니다.

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...");
            }
         }
      }
   } 
}

따라서 잠금 순서를 변경하는 것만으로도 프로그램이 교착 상태에 빠지는 것을 방지하고 다음과 같은 결과로 완료됩니다.

산출

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...

위의 예는 개념을 명확하게하기위한 것이지만 복잡한 개념이므로 교착 상태 상황을 처리하기위한 응용 프로그램을 개발하기 전에 자세히 살펴 봐야합니다.