Kami
Kami

Reputation: 1109

How to understand if wait() returned from timeout or from a notify()?

I have a waiting thread:

synchronized(sharedCounter) {
  while(sharedCounter > 0) {
    sharedCounter.wait(60000); //wait at most 1 minute
    /*if it wakens from the end of the timeout, it should break the loop
      or it could potentially restart the timeout*/
  }
}

And a thread that can notify:

synchronized (sharedCounter) {
  if(sharedCounter == 0) 
    sharedCounter.notify(); 
}

How can I distinguish a notify from a timeout?

I could do something like this:

synchronized(sharedCounter) {
  while(sharedCounter > 0) {
    sharedCounter.wait(60000); 
    if(sharedCounter == -1) { //if it was a notify()
      //I could save the fact that it was a notify() here
      break;
    }
    //Otherwirse, assume it was a timeout, save the fact and break
    break;
  }
}

synchronized (sharedCounter) {
   if(sharedCounter == 0) {
     sharedCounter = -1; //to signal that it comes from a notify()
     sharedCounter.notify(); 
   }
}

The problem is, that a spurious wake up would spoil my design.

How would you handle this problem?

Upvotes: 3

Views: 2418

Answers (3)

Alexei Kaigorodov
Alexei Kaigorodov

Reputation: 13535

This is a false problem. If, for example, wait returned by timeout, but immediately after that sharedCounter was set to -1 - do you still want to react to timeout, or to -1?

Upvotes: 0

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 280122

Use a more sophisticated concurrency primitive, a Condition. Acquire one from a Lock with Lock#newCondition(). You then have access to a Condition#await(long, TimeUnit) method which returns a boolean with a value of

false if the waiting time detectably elapsed before return from the method, else true

For example,

ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
// ... (share the object across threads)
if (condition.await(10, TimeUnit.SECONDS)) {
    // signaled (equivalent of notify)
} else {
    // time elapsed
}
// ... (in other thread)
condition.signal();

Spurious wakeups, unless otherwise specified in the Condition implementation documentation, are handled internally. You don't have to worry about them.

Upvotes: 9

Marcus Müller
Marcus Müller

Reputation: 36442

There is no way. You will have to add logic to your multithreaded application yourself to distinguish between these cases.

Upvotes: 1

Related Questions