2016-10-08 29 views
5

同步正常工作在這個代碼:爲什麼同步在第二個代碼中不起作用?

class PrintNumbers { 
     synchronized public void display() { 
      System.out.println("in display"); 
      for (int i = 0; i < 3; i++) { 
       System.out.println("Thread name : "+ Thread.currentThread().getName() + " i= " + i); 
       try { 
        Thread.sleep(1000); 
       } catch (InterruptedException e) { 
        e.getMessage(); 
       } 
      } 
      System.out.println("out of display"); 
     } 
    } 

    class MyThread implements Runnable { 
     Thread t; 
     PrintNumbers printNumbers; 

     MyThread(PrintNumbers printNumbers, String s) { 
      this.printNumbers = printNumbers; 
      t = new Thread(this,s); 
      t.start(); 
     } 

     public void run() { 
      printNumbers.display(); 
     } 
    } 

    class SyncExample { 
     public static void main(String[] args) { 
      PrintNumbers printNumbers = new PrintNumbers(); 

      new MyThread(printNumbers, "My Thread 1"); 
      new MyThread(printNumbers, "My Thread 2"); 
     } 
    } 

輸出:

in display 
Thread name : My Thread 1 i= 0 
Thread name : My Thread 1 i= 1 
Thread name : My Thread 1 i= 2 
out of display 
in display 
Thread name : My Thread 2 i= 0 
Thread name : My Thread 2 i= 1 
Thread name : My Thread 2 i= 2 
out of display 

但不是在這個代碼:

class PrintNumbers { 
     synchronized public void display() { 
      System.out.println("in display"); 
      for (int i = 0; i < 3; i++) { 
       System.out.println("Thread name : "+ Thread.currentThread().getName() + " i= " + i); 
       try { 
        Thread.sleep(1000); 
       } catch (InterruptedException e) { 
        e.getMessage(); 
       } 
      } 
      System.out.println("out of display"); 
     } 
    } 

    class MyThread implements Runnable { 
     Thread t; 
     PrintNumbers printNumbers; 

     MyThread(String s) { 
      this.printNumbers = new PrintNumbers(); 
      t = new Thread(this,s); 
      t.start(); 
     } 

     public void run() { 
      printNumbers.display(); 
     } 
    } 

    class SyncExample { 
     public static void main(String[] args) { 
      new MyThread("My Thread 1"); 
      new MyThread("My Thread 2"); 
     } 
    } 

輸出:

in display 
Thread name : My Thread 1 i= 0 
in display 
Thread name : My Thread 2 i= 0 
Thread name : My Thread 1 i= 1 
Thread name : My Thread 2 i= 1 
Thread name : My Thread 2 i= 2 
Thread name : My Thread 1 i= 2 
out of display 
out of display 

我不明白什麼區別wrt同步是否在可運行MyThread和SyncExample類中初始化PrintNumbers。請解釋。

+0

非靜態同步方法在'this'上進行同步。 – tkausl

+0

第二,你需要'display'方法是靜態的,它們鎖定了2個對象。 – passion

+1

您正在使用PrintNumbers的差異對象,鎖定位於對象級別。這就是爲什麼你得到不同的輸出。 – cody123

回答

5

我不明白什麼區別wrt同步是否可以在Runnable MyThread和SyncExample類中初始化PrintNumbers。

它沒有。什麼確實的問題是,在你的第一個例子中,你只有一個PrintNumbers這兩個線程共享的實例。但在第二個示例中,您有兩個單獨的PrintNumbers實例,每個線程一個。

由於PrintNumbers#display在實例上同步(​​實例方法在this上同步),它只在實例內同步,而不跨多個實例同步。

當兩個線程共享一個實例時,兩個對display的調用都被序列化。但是當每個線程都有自己的實例時,兩個對display的調用位於不同的實例中,因此沒有序列化的調用,它們可以重疊。

4

因爲在第二個代碼中每個線程都有自己的PrintNumbers對象,所以它們可以並行工作。在第一個中,他們共享單個對象並以同步的方式處理它。

PS。 請記住​​非靜態方法使對象上的同步(對於類上的靜態方法)。

3

它正在這兩種情況下工作,因爲它應該。不同的是,在第一種情況下,您有一個同步的單個對象。在第二個你有兩個。它們都只被調用一次,所以它們完全同步。

​​不能在對象之間工作,只能在一個對象之間工作。

相關問題