2016-10-08 2 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 

Я не могу понять, какая разница. Синхронизация делает для инициализации PrintNumbers в Runnable MyThread и в классе SyncExample. Пожалуйста, объясни.

+0

нестатические синхронизированные методы синхронизируются на 'this'. – tkausl

+0

Во-вторых, вам нужен статичный метод 'display', они блокируют 2 объекта. – passion

+1

Вы используете разностный объект PrintNumbers и блокировка находится на уровне объекта. Вот почему вы получаете разные результаты. – cody123

ответ

5

Я не могу понять, какая разница. Синхронизация делает для инициализации PrintNumbers в Runnable MyThread и в классе SyncExample.

Это не так. Что делает Дело в том, что в вашем первом примере у вас есть только одинPrintNumbers экземпляр, который разделяет обе темы. Но в вашем втором примере у вас есть два отдельных экземпляра PrintNumbers, по одному для каждого потока.

С PrintNumbers#display синхронизирует по экземпляру (synchronized методы экземпляра синхронизируются по this), он синхронизируется только в экземпляре, а не через несколько экземпляров.

Когда оба потока совместно используют экземпляр, два вызова на display сериализуются. Но когда каждый поток имеет свой собственный экземпляр, два вызова display находятся в отдельных экземплярах, и поэтому сериализация вызовов не происходит, они могут перекрываться.

4

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

PS. Помните, что synchronized для нестатических методов выполняет синхронизацию по объекту (для статических методов в классе).

3

Он работает в обоих случаях как следует. Разница в том, что в первом случае у вас есть единственный объект, который синхронизирован. Во втором у вас есть два. Оба они вызываются только один раз, поэтому они синхронизируются отлично.

synchronized не работает между объектами, только в пределах одного.