Хотя против если в потоке-синхронизации - PullRequest
0 голосов
/ 23 октября 2018

У меня есть два набора кода, где я пытаюсь напечатать алфавиты и цифры один за другим. Один использует «цикл цикла», а другой использует «если».

public class Alphabets {

  public static void main(String[] args) {

          AN an= new AN(false);

          Thread t1=new Thread(new Runnable() {

            @Override
            public void run() {             
                try {                       
                    an.Alpha();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });              

          Thread t2= new Thread(new Runnable() {                
            @Override
            public void run() {
                try {
                    an.numbers();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }                   
            }
        });                   
          t1.start();
          t2.start();
   }
}

class AN {  
  boolean flag; 
  AN(boolean flag) {
    this.flag=flag;
  }
  synchronized void Alpha() throws InterruptedException {       
    for(char i='A'; i<='Z';i++) {
        while(flag==false) { // I have replaced "while" with "if" in my second code         
          System.out.println(+i);
          notifyAll();
          flag=true;
        }           
        wait();         
    }
  }    
  synchronized void numbers() throws InterruptedException {     
    for(int i=1;i<=26;i++) {            
        while(flag==true) {// I have replaced "while" with "if" in my second code           
          System.out.println(+i);
          notifyAll();
          flag=false;
        }           
        wait();         
    }
  }     
}

Набор 1с помощью цикла "while" выдает следующий вывод:

65 1 66 2 67 3 68 4

Установка 2 с помощью "if" дает следующий вывод:

65 1 673 69 5 71 7

Обратите внимание, что 65 66 - это коды ASCII для A, B и т. Д.

Может кто-нибудь объяснить, почему эти два кода ведут себя так. Я не могу понятьэто из.Пожалуйста, объясните подробно.

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

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

Использование if или while не влияет на сам код, оно просто вызывает фактическую проблемучаще.

Способ решить эту проблему заключается в цикле ожидания, пока состояние фактически не изменится:

for(char i='A'; i<='Z';i++) {
    if(flag==false) {          
      System.out.println(+i);
      notifyAll();
      flag=true;
    } 
    while (flag == true) {    // spurious wakeup prevention      
      wait();         
    }
}
0 голосов
/ 24 октября 2018

while loop предпочтительнее в многопоточности, потому что он предотвращает от spurious wake up, что означает, что метод wait () может возвращаться без уведомления от пользовательского потока, вероятно, сделанный OS scheduler.В вашем случае, я думаю, что из-за spurious wakeup if() condition пропускается и снова переходит к wait().

...