2016-10-03 5 views
0

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

class Table { 
    void printTable(int n) { //method not synchronized 
     for(int i=1; i<=10; i++) { 
      System.out.println(n + " * " + i + " = " + n*i); 
      try { 
       Thread.sleep(500); 
      } catch(Exception e) { 
       System.out.println(e); 
      } 
     } 
     System.out.println("Table of " + n + " is completed."); 
    } 
} 

class MyThread extends Thread { 
    Table t; 
    int num; 

    MyThread(Table t, int num) { 
     this.t = t; 
     this.num = num; 
    } 

    public void run() { 
     synchronized(t) { 
     t.printTable(num); 
     } 
    } 
} 

class TestSynchronization { 
    public static void main(String[] args) { 
     Table obj = new Table(); //only one object 
     MyThread t1; 
     MyThread t2; 

     t1 = new MyThread(obj, 10); 
     t2 = new MyThread(obj, 17); 

     t1.start(); 
     t2.start(); 
    } 
} 

Это выход, как это:

10 * 1 = 10 
10 * 2 = 20 
10 * 3 = 30 
10 * 4 = 40 
10 * 5 = 50 
Table of 10 is completed. 
17 * 1 = 17 
17 * 2 = 34 
17 * 3 = 51 
17 * 4 = 68 
17 * 5 = 85 
Table of 17 is completed. 

которая кажется адекватной, но когда я пытаюсь сделать то же самое, удалив синхронизированный блок из метода выполнения и appying его в obj объект void main он показывает разные вывод.

class Table { 
    void printTable(int n) { //method not synchronized 
     for(int i=1; i<=5; i++) { 
      System.out.println(n + " * " + i + " = " + n*i); 
      try { 
       Thread.sleep(500); 
      } catch(Exception e) { 
       System.out.println(e); 
      } 
     } 
     System.out.println("Table of " + n + " is completed."); 
    } 
} 

class MyThread extends Thread { 
    Table t; 
    int num; 

    MyThread(Table t, int num) { 
     this.t = t; 
     this.num = num; 
    } 

    public void run() { 
     t.printTable(num); 
    } 
} 

class TestSynchronization { 
    public static void main(String[] args) { 
     Table obj = new Table(); //only one object 
     MyThread t1; 
     MyThread t2; 

     synchronized(obj) { 
     t1 = new MyThread(obj, 10); 
     t2 = new MyThread(obj, 17); 
     } 

     t1.start(); 
     t2.start(); 
    } 
} 

Выход:

10 * 1 = 10 
17 * 1 = 17 
10 * 2 = 20 
17 * 2 = 34 
17 * 3 = 51 
10 * 3 = 30 
17 * 4 = 68 
10 * 4 = 40 
10 * 5 = 50 
17 * 5 = 85 
Table of 17 is completed. 
Table of 10 is completed. 

Почему это не работает во втором случае, пожалуйста, объясните мне.

Также предлагайте мне способ, которым я могу получить тот же вывод, используя синхронизированный блок в void main, если это возможно.

+0

Почему при голосовании оп? вопрос выглядит совершенно разумным для меня .. если вы не думаете, что это вопрос домашней работы, который ... hmmm – ultrajohn

ответ

1

Разница заключается в том, где и , когдаlock на объект класса Таблица была приобретена.

В первом примере блокировка объекта таблицы была приобретена внутри экземпляров класса MyThread. Предположим, что первый экземпляр класса MyThread обретает блокировку объекта таблицы, никакие другие экземпляры класса MyThread не смогут получить блокировку для объекта таблицы до тех пор, пока первый не выпустит его. A.k.a., Синхронизация на уровне нитей.

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

+0

Спасибо @ultrajohn. Теперь я ошибся. Также поняла концепция. На самом деле я очень новичок в Java Synchronization, поэтому я не мог получить эту концепцию. –

+1

@Niraj, No prob. Пожалуйста, сделайте мне одолжение и голосуйте за мой пост. :) Благодаря. – ultrajohn

+0

Конечно. @ultrajohn –

0

Синхронизированный блок представляет собой комнату и синхронизированный блок применяется к объекту. В первом примере Синхронизированный блок применяется к объекту таблицы классов. Когда какой-либо поток пытается получить доступ к методу, он должен сначала ввести Синхронизированный блок, как человек, входящий в комнату, и когда поток, подобный t1, входит в блок, комната блокируется до тех пор, пока выполнение не будет завершено с помощью t1, и только после этого можете вставить t2 в комнату.

Без синхронизированного блока потоки чередуются друг с другом, и, следовательно, выход отличается, иногда бывает корректным вывод, если t1 завершает выполнение непосредственно перед началом t2, но в случае большого приложения он будет мешать и будет вызывать различие как вы упомянули во втором примере. Так что для того, чтобы предотвратить такое interleiving мы используем синхронизированные блоки или thrcead безопасные классы, как, блокирование очереди и т.д.

0

синхронизированный блок

synchronized(mutex){ 
    x =y; 
    y=z; 
    } 

мьютекса = взаимоисключающие. Блок, который может выполняться одним потоком из списка тем, которые имеют один и тот же объект, т. Е. Mutex

Прежде всего, мьютекс - это объект, и каждый объект в java имеет полуформу, называемую блокировкой.

если нить А и В имеют общий семафор, как с затем Потоком A перед входом синхронизации блока будет приобретать блокировку т.е. приобретает случаться перед входом

и релиз произойдет до приобретения, т.е. если один поток уже приобрело замок затем другой поток должен ждать, пока первый поток не освободит блокировку.

еще одна особенность синхронизирующего блока - каждый поток, который приобрел блокировку, должен прочитать всю переменную, участвующую в блоке, непосредственно из основной памяти вместо значения останова из кеша, и должен записать те, которые были изменены, в основную память, прежде чем покинуть блок.

i.e обновление значения переменной происходит после приобретения и записи памяти перед выпуском, поэтому следующий поток будет иметь самое последнее значение для обработки.

Смежные вопросы