简体   繁体   English

Java并发 - 虚假唤醒和等待(超时)

[英]Java concurrent - spurious wakeups and wait(timeout)

I have learned that when waiting on an object, the condition should be placed in a loop instead of within a single if condition . 我已经了解到,在等待一个对象时, 条件应该放在循环中而不是在单个if condition One reason for that is to avoid various spurious wakeup calls that might occur. 其中一个原因是避免可能发生的各种虚假唤醒呼叫。

For example: 例如:

synchronized (obj) {
    while (condition is false) {
        obj.wait(5 * 1000);
    }
    ... do something ...
}

However, I only want to wait 5 seconds for the thread to be notified. 但是,我只想等待5秒钟才能通知线程。 In the code above, the thread waits for 5 seconds. 在上面的代码中,线程等待5秒。 But after that period, if the condition is still false, we wait again. 但在那段时间之后,如果情况仍然是假的,我们会再次等待。 This would not be the case if I had the following: 如果我有以下情况,情况就不是这样了:

synchronized (obj) {
    if (condition is false) {
        obj.wait(5 * 1000);
    }
    ... do something ...
}

But this contradicts the guideline we should use a loop instead of a single if condition! 但这与指南相矛盾,我们应该使用循环而不是单个if条件!

How is this solved? 这是怎么解决的?

here's how i typically handle this: 这是我通常如何处理这个:

long timeout = ....;
synchronized(obj) {
  long start = System.currentTimeMillis();
  while(!condition && (timeout > 0)) {
    obj.wait(timeout);
    long now = System.currentTimeMillis();
    timeout -= (now - start);
    start = now;
  }
}

Answering my own question, this might work: 回答我自己的问题,这可能有效:

synchronized (obj) {
    for (long time = System.currentTimeMillis() + timeout; !condition && System.currentTimeMillis() < time; ) {
        obj.wait(time - System.currentTimeMillis());
    }
    if (condition) {
        ... do something ...
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM