2017-06-12 49 views
1

我有這個簡單的Java程序,利用監視器,讓客戶進入登機區。我想我把wait()和notify()語句放在導致程序死鎖的錯誤位置,但是,我無法自己弄清楚它。以下是我寫的代碼。簡單的程序使用Java監視器

public class AdultCouple extends Thread 
{ 
    private boolean onRide = false; 
    private int ID; 

    AdultCouple(int ID) 
    { 
     this.ID = ID; 
    } 

    public synchronized void getIn() 
    { 
     while (!Main.isDoorOpen) 
     { 
      try 
      { 
       wait(); 
      } 
      catch (InterruptedException ex) 
      { 

      } 
      System.out.println("Go through"); 
     } 
     System.out.println("Couple " + ID + " get in boarding area."); 
     onRide = true; 
     Main.peopleInBoardingArea++; 
     notify(); 
    } 

    public void run() 
    { 
     getIn(); 
    } 
} 


public class Area extends Thread 
{ 

    Area() 
    { 
    } 

    public synchronized void openDoor() 
    { 
     while (Main.peopleInBoardingArea != 0) 
     { 
      try 
      { 
       wait(); 
      } 
      catch (InterruptedException ex) 
      { 
      } 
     } 
     System.out.println("Area opens"); 
     Main.isDoorOpen = true; 
     notifyAll(); 
    } 

    public synchronized void closeDoor() 
    { 
    } 


    public void run() 
    { 
     openDoor(); 
    } 
} 


public class ParentKid extends Thread 
{ 

    private boolean onRide = false; 
    private int ID; 

    ParentKid(int ID) 
    { 
     this.ID = ID; 
    } 

    public synchronized void getIn() 
    { 
     while (!Main.isDoorOpen) 
     { 
      try 
      { 
       wait(); 
      } 
      catch (InterruptedException ex) 
      { 

      } 
      System.out.println("Go through"); 
     } 
     System.out.println("Couple " + ID + " get in boarding area."); 
     onRide = true; 
     Main.peopleInBoardingArea++; 
     notify(); 
    } 

    public void run() 
    { 
     getIn(); 
    } 

} 

public class Main 
{ 

    public static boolean isDoorOpen = false; 
    public static int peopleInBoardingArea = 0; 

    public static void main(String args[]) 
    { 
     Thread t3 = new Area(); 
     Thread t1 = new ParentKid(1); 
     Thread t2 = new AdultCouple(2); 


     t1.start(); 
     t2.start(); 
     t3.start(); 

     try 
     { 
      t1.join(); 
      t2.join(); 
      t3.join(); 
     } 
     catch (InterruptedException ex) 
     { 

     } 
    } 
} 
+0

一個問題是,您正在使用對「Main」類的靜態字段的非同步訪問。即使將它們更改爲'volatile'也不適用於'++'操作符。 – Andreas

回答

0

問題是你在不同的對象上同步。當你寫這樣的東西

public synchronized foo() {...} 

你在這個對象上同步。在你的情況下,你在當前線程上同步,這沒有任何意義。你應該在同一個對象上進行同步。

public class Main { 

    public static Object lock = new Object(); 
    ... 
} 

public class AdultCouple extends Thread 
{ 
    private boolean onRide = false; 
    private int ID; 

    AdultCouple(int ID) 
    { 
     this.ID = ID; 
    } 

    public void getIn() 
    { 
     synchronized (Main.lock) { 
      while (!Main.isDoorOpen) { 
       try { 
        Main.lock.wait(); 
       } catch (InterruptedException ex) { 

       } 
       System.out.println("Go through"); 
      } 
      System.out.println("Couple " + ID + " get in boarding area."); 
      onRide = true; 
      Main.peopleInBoardingArea++; 
      Main.lock.notifyAll(); 
     } 
    } 

    public void run() 
    { 
     getIn(); 
    } 
} 

public class Area extends Thread 
{ 

    Area() 
    { 
    } 

    public void openDoor() 
    { 
     synchronized (Main.lock) { 
      while (Main.peopleInBoardingArea != 0) { 
       try { 
        Main.lock.wait(); 
       } catch (InterruptedException ex) { 
       } 
      } 
      System.out.println("Area opens"); 
      Main.isDoorOpen = true; 
      Main.lock.notifyAll(); 
     } 
    } 

    public synchronized void closeDoor() 
    { 
    } 


    public void run() 
    { 
     openDoor(); 
    } 
} 

public class ParentKid extends Thread 
{ 

    private boolean onRide = false; 
    private int ID; 

    ParentKid(int ID) 
    { 
     this.ID = ID; 
    } 

    public void getIn() 
    { 
     synchronized (Main.lock) { 
      while (!Main.isDoorOpen) { 
       try { 
        Main.lock.wait(); 
       } catch (InterruptedException ex) { 

       } 
       System.out.println("Go through"); 
      } 
      System.out.println("Kid " + ID + " get in boarding area."); 
      onRide = true; 
      Main.peopleInBoardingArea++; 
      Main.lock.notifyAll(); 
     } 
    } 


    public void run() 
    { 
     getIn(); 
    } 

} 

也不要使用notify(),而是使用notifyAll()。我沒有看到任何理由使用它