Java Eşzamanlılığı - Kilitlenme

Kilitlenme, iki veya daha fazla iş parçacığının sonsuza kadar engellendiği ve birbirini beklediği bir durumu tanımlar. Kilitlenme, birden çok iş parçacığının aynı kilide ihtiyaç duyması, ancak bunları farklı sırayla elde etmesi durumunda oluşur. Çok iş parçacıklı bir Java programı, kilitlenme durumundan zarar görebilir, çünküsynchronizedanahtar sözcüğü, çalıştırılan iş parçacığının belirtilen nesne ile ilişkili kilit veya izlemeyi beklerken engellenmesine neden olur. İşte bir örnek.

Misal

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

Yukarıdaki programı derleyip çalıştırdığınızda, bir kilitlenme durumu bulursunuz ve program tarafından üretilen çıktı şu şekildedir:

Çıktı

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

Yukarıdaki program sonsuza kadar askıda kalacaktır çünkü iş parçacıkları hiçbiri ilerlemek için pozisyonda değildir ve birbirinin kilidi açmasını beklememektedir, böylece CTRL + C tuşlarına basarak programdan çıkabilirsiniz.

Kilitlenme Çözüm Örneği

Her iki iş parçacığının hala birbirini bekleyip beklemediğini görmek için aynı programın kilit ve çalıştırma sırasını değiştirelim -

Misal

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

Yani kilitlerin sırasını değiştirmek, programın kilitlenme durumuna girmesini engeller ve aşağıdaki sonuçla tamamlanır -

Çıktı

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

Yukarıdaki örnek sadece kavramı açıklığa kavuşturmaktır, ancak bu karmaşık bir kavramdır ve uygulamalarınızı kilitlenme durumlarıyla başa çıkmak için geliştirmeden önce onu derinlemesine incelemelisiniz.