简体   繁体   English

Java wait()方法的行为

[英]the behavior of Java wait() method

Suppose that a token machine can only issue one token at a time. 假设令牌机器一次只能发行一个令牌。 The rule is that one token must be consumed before another one can be created. 规则是必须先消耗一个令牌,然后才能创建另一个令牌。

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;
}

My question is that can I change the 'while' expression in previous code to 'if' instead without vandalize the rule? 我的问题是,我可以在不破坏规则的情况下将之前代码中的“ while”表达式更改为“ if”吗? Many thanks. 非常感谢。

Thanks guys for answering my question, I checked a lot online, find the following info are helpful: A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. 谢谢大家回答我的问题,我在网上进行了很多检查,发现以下信息对您有帮助:线程也可以唤醒,而不会被通知,中断或超时,即所谓的虚假唤醒。 While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied. 尽管在实践中这种情况很少发生,但是应用程序必须通过测试应该导致线程唤醒的条件来防范它,并在条件不满足时继续等待。 In other words, waits should always occur in loops. 换句话说,等待应该总是在循环中发生。

Apparently, the spurious wakeup is an issue (I doubt that it is a well known issue) that intermediate to expert developers know it can happen but it just has been clarified in JLS third edition which has been revised as part of JDK 5 development. 显然,虚假唤醒是一个问题(我怀疑这是一个众所周知的问题),对于专业开发人员而言,中级人员知道会发生这种情况,但JLS第三版对此做了澄清,该版本已作为JDK 5开发的一部分进行了修订。 The javadoc of wait method in JDK 5 has also been updated JDK 5中的wait方法的javadoc也已更新

You need to use while to avoid waking up the thread in case of Spurious wake ups . 您需要使用while来避免由于虚假唤醒而唤醒线程。 In case of a spurious wake-up, a thread can be woken up without notify() being called. 在虚假唤醒的情况下,可以在不调用notify()情况下唤醒线程。 The while loop will recheck the condition and proceed only if it is a genuine notify call and not a spurious reactivation. 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