2014-09-28 55 views
0

這是原來的代碼修改用於同步的碼的結果:困惑與我在Java

// Demonstrating multithreading and thread synchronization in Java 
public class ForkExample implements Runnable { 

    int i; // the ID of the thread, so we can control behavior 
    boolean busy; // the flag, Thread 1 will wait until Thread 0 is no longer busy before continuing 
    ForkExample other; // reference to the other thread we will synchronize on. This is needed so we can control behavior. 

    // create the runnable object 
    public ForkExample(int i, ForkExample other) { 
     this.i = i; // set the thread ID (0 or 1) 
     if (i == 0) 
      busy = true; // set the busy flag so Thread 1 waits for Thread 0 
     else 
      this.other = other; 
    } 

    // synchronized method to test if thread is busy or not 
    public synchronized boolean isBusy() { 
     return busy; 
    } // What happens if this isn't synchronized? 

    // run method needed by runnable interface 
    public void run() { 
     if(i == 0) // 1st thread, sleep for a while, then notify threads waiting 
      try { 
       Thread.sleep(4000); // What happens if you put this sleep inside the synchronized block? 
       synchronized(this) { 
        notify(); // notify() will only notify threads waiting on *this* object; 
       } 
       Thread.sleep(4000); // What happens if you put this sleep inside the synchronized block? 
       synchronized(this) { 
        busy = false; // must synchronize while editing the flag 
        notify(); // notify() will only notify threads waiting on *this* object; 
       } 
      } catch(InterruptedException tie) { 
       tie.printStackTrace(); 
      } 
     else { 
      while(other.isBusy()) { // check if other thread is still working 
       System.out.println("Waiting!"); 
       // must sychnronize to wait on other object 
       try { 
        synchronized(other) { 
         other.wait(); 
        } 
       } // note we have synchronized on the object we are going to wait on 
       catch(InterruptedException tie) { 
        tie.printStackTrace(); 
       } 
      } 
      System.out.println("Finished!"); 
     } 
    } 

    public static void main(String[] args) { 
     ForkExample t1 = new ForkExample(0, null); 
     ForkExample t2 = new ForkExample(1, t1); 
     (new Thread(t2)).start(); 
     (new Thread(t1)).start(); 
    } 

} 

這是原來的代碼與我的修改:

// Demonstrating multithreading and thread synchronization in Java 
public class ForkExample implements Runnable { 

    // the ID of the thread, so we can control behavior 
    int i; 
    // the flag, Thread 1 will wait until Thread 0 is no longer busy before continuing 
    boolean busy; 
    // reference to the other thread we will synchronize on. This is needed so we can control behavior. 
    ForkExample other; 

    // create the runnable object 
    public ForkExample(int i, ForkExample other) { 
     this.i = i; // set the thread ID (0 or 1) 
     if (i == 0) 
      busy = true; // set the busy flag so Thread 1 waits for Thread 0 
     else 
      this.other = other; 
    } 

    // synchronized method to test if thread is busy or not 
    public boolean isBusy() { 
     if (busy) /*** Added if/else statement to tell user if the thread is still busy. ***/ 
      System.out.print("Still busy, "); 
     else 
      System.out.print("Thread is no longer busy, "); 
     return busy; 
    } // What happens if this isn't synchronized? 
    /*** Method still works even without being synchronized ***/ 

    // run method needed by runnable interface 
    public void run() { 
     if(i == 0) // 1st thread, sleep for a while, then notify threads waiting 
      try { 
       synchronized(this) { 
        Thread.sleep(4000); // What happens if you put this sleep inside the synchronized block? 
        /*** All statements in this block still goes through after notify(), but t1 is asleep ***/ 
        System.out.println("yo"); 
        notify(); // notify() will only notify threads waiting on *this* object; 
        /*** This notify doesn't work ***/ 
        System.out.println("sup"); 
       } 
       System.out.println("stop synchronization"); 
       /*** somehow forces synchronized(this) as another method call ***/ 
       synchronized(this) { 
        System.out.println("hey"); 
        Thread.sleep(1000); // What happens if you put this sleep inside the synchronized block? 
        System.out.println("hello"); 
        busy = false; // must synchronize while editing the flag 
        notify(); // notify() will only notify threads waiting on *this* object; 
        /*** This notify does not work either ***/ 
        System.out.println("que?"); 
       } 
       synchronized(this) { 
        System.out.println("yes"); 
        notify(); 
        /*** This notify works if the "stop synchronization statement exists ***/ 
       } 
       Thread.sleep(1000); 
       synchronized(this) { 
        System.out.println("hey again"); 
        notify(); 
       } 
       /*** Other thread finally executes since t1 sleeps for 1 second ***/ 
      } catch(InterruptedException tie) { 
       tie.printStackTrace(); 
      } 
     else { 
      while(other.isBusy()) { // check if other thread is still working 
       System.out.println("Waiting!"); 
       // must synchronize to wait on other object 
       try { synchronized(other) { other.wait(); } } 
       // note we have synchronized on the object we are going to wait on 
       catch(InterruptedException tie) { tie.printStackTrace(); } 
       System.out.println("All threads done!"); 
       /*** Sysout here since this mod allows only one pass ***/ 
      } 
      System.out.println("Wrapping up..."); /*** Lets user know that finishing will take a moment. ***/ 
      try { 
       Thread.sleep(3000); 
      } catch (InterruptedException tie) { 
       tie.printStackTrace(); 
      } 
      System.out.println("Finished!"); 
     } 
    } 

    public static void main(String[] args) { 
     ForkExample t1 = new ForkExample(0, null); 
     ForkExample t2 = new ForkExample(1, t1); 
     (new Thread(t2)).start(); 
     (new Thread(t1)).start(); 
     System.out.println("End of Main method"); /*** Added sysout to see how threads work ***/ 
    } 

} 

這是輸出:

End of Main method 
Still busy, Waiting! 
yo 
sup 
stop synchronization 
hey 
hello 
que? 
yes 
All threads done! 
Thread is no longer busy, Wrapping up... 
hey again 
Finished! 

爲什麼第三個notify()是唯一一次通過?

+0

你能澄清你的問題嗎? – 2014-09-28 04:22:00

回答

1

首先,Thread#sleep(long)不會放棄任何獲取的對象鎖。

你的應用程序基本上是一個大的競爭條件,併發生在線程調度程序的判斷。

唯一notify(),將重要的是,的wait()後會發生之一。 javadoc of notify()狀態

被喚醒的線程將無法繼續,直到當前線程放棄對該對象的鎖定。

所以,無論是哪一個真正喚醒其他線程,其他線程將仍然有​​塊內等到調用線程釋放鎖,即。保留​​塊(並且不輸入另一個​​塊)。