2016-06-03 1 views
-3

В этой многопоточной программе потоки «t1» и «t2» пытаются выполнить синхронизированный метод printTable() на том же объекте obj. Когда t1 запускается и printTable() вызывается из его метода run(), t2 должен ждать, пока t1 не закончит выполнение синхронизированного метода; почему этого не происходит? Почему выходные данные несортированы?Почему метод не получает доступ синхронно по потокам в этой программе Java?

Вот программа:

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

public class TestSynchronization3{ 
    public static void main(String args[]){ 
     final Table obj = new Table();//only one object 
      Thread t1=new Thread(){ 
       public void run(){ 
        obj.printTable(5); 
       } 
      }; 
      Thread t2=new Thread(){ 
       public void run(){ 
        obj.printTable(100); 
       } 
      }; 
      t1.start(); 
      t2.start(); 
     } 
} 
+6

Вы никогда не использовали ключевое слово 'synchronized' для объявления метода как синхронного – Michael

ответ

4

Вам нужно добавить ключевое слово synchronized перед методом printTable() в классе Table как отметил Michael. Изменение подписи функции printTable() от

void printTable(int n){...} 

в

synchronized void printTable(int n){...} 

Это производит вывод как:

100 
200 
300 
400 
500 
5 
10 
15 
20 
25 

или

5 
10 
15 
20 
25 
100 
200 
300 
400 
500 
0

Почему этого не происходит? Почему выходные данные несортированы?

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

Только потому, что вы запускаете нить obj.printTable(5); перед потоком obj.printTable(100); в своем коде, это не гарантирует, что потоки выполняются в этом порядке. Как показывает @user5794376, когда начинаются два потока, есть гонка, чтобы узнать, кто первый, кто звонит printTable(...), и кто затем должен ждать окончания другого потока. Темы выполняются асинхронно, и невозможно предсказать, какой из них выиграет и будет гарантировать заказ.

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

Еще одна вещь, которую нужно попробовать - запустить printTable(...) из двух потоков без синхронизации вообще. System.out.println(...) - это синхронизированный метод, так что это нормально. Вероятно, вы увидите тот же результат, потому что, опять же, один поток получает и запускает все 5 своих операторов println(...) перед тем, как начинается другой. Если вы действительно хотите видеть чередование, тогда вы должны увеличить 5 до 5000000. Затем вы должны увидеть блок вывода *5, а затем блок вывода *100.

Надеюсь, это поможет.