2016-10-08 22 views
5

Synchronizacja działa poprawnie w tym kodzie:Dlaczego synchronizacja nie działa w drugim kodzie?

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

wyjściowa:

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 

ale nie w tym kodzie:

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

wyjściowa:

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 

Nie mogę zrozumieć, co różni się od synchronizacji, aby zainicjować PrintNumbers w Runnable MyThread iw klasie SyncExample. Proszę wytłumacz.

+0

Niestatyczne metody synchronizowane synchronizują się na "tym". – tkausl

+0

Po drugie, potrzebujesz metody "display" statycznej, blokują 2 obiekty. – passion

+1

Używasz obiektu różnicowego PrintNumbers, a blokada znajduje się na poziomie obiektu. Właśnie dlatego uzyskujesz różne wyniki. – cody123

Odpowiedz

5

Nie mogę zrozumieć, co różni się od synchronizacji, aby zainicjować PrintNumbers w Runnable MyThread iw klasie SyncExample.

Nie dotyczy. Znaczenie ma to, że w pierwszym przykładzie masz tylko jedną instancję, z którą oba wątki współużytkują. Ale w twoim drugim przykładzie masz dwie oddzielne instancje PrintNumbers, po jednej dla każdego wątku.

Ponieważ PrintNumbers#display synchronizuje się z instancją (synchronized metody synchronizacji na), synchronizuje się tylko w obrębie instancji, a nie w wielu instancjach.

Gdy oba wątki współużytkują instancję, dwie wywołania do display są serializowane. Ale gdy wątki mają własne instancje, dwa wywołania do display są w oddzielnych instancjach, a zatem nie ma serializacji wywołań, mogą się nakładać.

4

Ponieważ w drugim kodzie każdy wątek ma własny obiekt PrintNumbers, dzięki czemu działają one równolegle. W pierwszym mają wspólny obiekt PrintNumbers i pracują z nim w sposób zsynchronizowany.

PS. Należy pamiętać, że metoda synchronized dla metod niestatycznych powoduje synchronizację obiektu (dla metod statycznych w klasie).

3

Działa w obu przypadkach tak, jak powinien. Różnica polega na tym, że w pierwszym przypadku mamy pojedynczy obiekt, który jest zsynchronizowany. W drugim masz dwa. Oba są wywoływane tylko raz, więc są doskonale zsynchronizowane.

synchronized nie działa między obiektami, tylko w jednym.

Powiązane problemy