Java синхронизирована, кажется, игнорируется - PullRequest
4 голосов
/ 23 марта 2010

У меня есть следующий код, который я ожидал заблокировать после распечатки «Main: pre-sync». Но похоже, что synchronized не делает то, что я ожидаю. Что здесь происходит?

import java.util.*;

public class deadtest {
   public static class waiter implements Runnable {
      Object obj;

      public waiter(Object obj) {
         this.obj = obj;
      }

      public void run() {
         System.err.println("Thead: pre-sync");
         synchronized(obj) {
            System.err.println("Thead: pre-wait");
            try {
               obj.wait();
            } catch (Exception e) {
            }
            System.err.println("Thead: post-wait");
         }
         System.err.println("Thead: post-sync");
      }
   }

   public static void main(String args[]) {
      Object obj = new Object();

      System.err.println("Main: pre-spawn");

      Thread waiterThread = new Thread(new waiter(obj));
      waiterThread.start();

      try {
         Thread.sleep(1000);
      } catch (Exception e) {
      }  

      System.err.println("Main: pre-sync");
      synchronized(obj) {
         System.err.println("Main: pre-notify");
         obj.notify();
         System.err.println("Main: post-notify");
      }
      System.err.println("Main: post-sync");

      try {
         waiterThread.join();
      } catch (Exception e) {
      }
   }
}

Поскольку оба потока синхронизируются на созданном объекте, я ожидал, что потоки фактически блокируют друг друга. В настоящее время код успешно уведомляет другой поток, присоединяется и выходит.

Ответы [ 2 ]

4 голосов
/ 23 марта 2010

Вызов .wait() на мониторе фактически снимает синхронизированную блокировку, поэтому другой поток может подключиться к тому же монитору и отправить уведомление.

Ваше поведение совершенно нормально: «официант» блокирует монитори затем снимает блокировку при ожидании уведомления.Через 1 секунду основной поток блокирует монитор, отправляет уведомление, разблокирует монитор, который будит официанта для завершения его работы.

4 голосов
/ 23 марта 2010

Когда вы wait() на объекте, поток снимает блокировку на объекте, чтобы другие могли получить блокировку и notify() ожидающий поток. См. Javadoc для Object.wait().

Текущий поток должен владеть монитором этого объекта. Поток освобождает владельца этого монитора и ожидает, пока другой поток не уведомит потоки, ожидающие на мониторе этого объекта, чтобы он проснулся либо посредством вызова метода notify или метода notifyAll. Затем поток ожидает, пока он не сможет вновь получить право собственности на монитор, и возобновит выполнение .

...