簡體   English   中英

Java wait()方法的行為

[英]the behavior of Java wait() method

假設令牌機器一次只能發行一個令牌。 規則是必須先消耗一個令牌,然后才能創建另一個令牌。

class TokenMachine {
    private int tokenID;
    private boolean tokenExists = false;
    public synchronized void createToken(int coup){
      ...
    }
    public synchronized int consumeToken(){
      ...
    }
}

public synchronized void createToken(int coup) {
    while(tokenExists) { //can I change 'while' to 'if'?
        wait(); //in a try-catch block
    }
    this.tokenID = coup;
    tokenExists = true;
    notify();
}

public synchronized int consumeToken() {
    while(!tokenExists) { //can I change 'while' to 'if'?
        wait(); //in a try-catch block
    }
    tokenExists = false;
    notify();
    return tokenID;
}

我的問題是,我可以在不破壞規則的情況下將之前代碼中的“ while”表達式更改為“ if”嗎? 非常感謝。

謝謝大家回答我的問題,我在網上進行了很多檢查,發現以下信息對您有幫助:線程也可以喚醒,而不會被通知,中斷或超時,即所謂的虛假喚醒。 盡管在實踐中這種情況很少發生,但是應用程序必須通過測試應該導致線程喚醒的條件來防范它,並在條件不滿足時繼續等待。 換句話說,等待應該總是在循環中發生。

顯然,虛假喚醒是一個問題(我懷疑這是一個眾所周知的問題),對於專業開發人員而言,中級人員知道會發生這種情況,但JLS第三版對此做了澄清,該版本已作為JDK 5開發的一部分進行了修訂。 JDK 5中的wait方法的javadoc也已更新

您需要使用while來避免由於虛假喚醒而喚醒線程。 在虛假喚醒的情況下,可以在不調用notify()情況下喚醒線程。 while循環將重新檢查條件,並且僅當它是真正的notify調用而不是偽激活時才繼續。

class TokenMachine {
  ArrayBlockingQueue<Integer> q=new ArrayBlockingQueue<Integer>(1);

  public synchronized void createToken(int coup){
    q.put(coup);
  }

  public synchronized int consumeToken(){
    return q.get();
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM