First, this is a near duplicate of: How to differentiate when wait(long timeout) exit for notify or timeout?
But it is a new follow-on question.
Having this wait declaration:
public final native void wait(long timeout) throws InterruptedException;
It could exit by InterruptedException, or by timeout, or because Notify/NotifyAll method was called in another thread, Exception is easy to catch but...
My code absolutely needs to know if the exit was from timeout or notify. (In the future, this code needs to be redesigned, but that cannot be done now. So I need to know the reason for the exit from wait.)
Specifically, can someone give an example of using a ThreadLocal Boolean that is set to true only on notify() and where all this is inside an existing loop as shown below? (This was more or less the accepted answer in the other thread, but no specific code example was given. I'm not all that familiar with Java, so I need a specific code example -- ideally in the context of the existing code below.)
public synchronized int getLastSequenceNumber() {
while (empty) {
try {
wait(waitTimeValue);
} catch (InterruptedException e) {}
}
empty = true;
return reportedSequenceNumber;
}
public synchronized void reconcileLastSequenceNumber(int sequenceNumber) {
empty = false;
this.reportedSequenceNumber = sequenceNumber;
notifyAll();
}
the Boolean "empty" serves a purpose outside of the specific question I'm asking here. I believe I will need to add another Boolean to fulfill the suggested answer from the original question. How would I integrate that proposed solution into the existing code snippet above? Thanks.
The wait() method causes the current thread to wait until another thread invokes the notify() or notifyAll() methods for that object. The notify() method wakes up a single thread that is waiting on that object's monitor. The notifyAll() method wakes up all threads that are waiting on that object's monitor.
The notify() method chooses one thread that is waiting on the monitor held by the current thread and wakes it up. Typically, the waiting thread will grab the monitor and proceed.
If no threads are waiting in the waiting queue, then notify() and notifyAll() have no effect. Before calling the notify() or notifyAll() method of an object, a thread must own the lock of the object. Hence it must be in one of the object's synchronized methods or synchronized block.
Sr. No. In the case of the multiThreading, notify() method sends the notification to only one thread among the multiple waiting threads which are waiting for the send lock. While notifyAll() methods in the same context send notifications to all waiting threads instead of a single thread.
You might be better off using a Condition
(and its await
method) rather than built-in monitors, because await
returns a boolean
value indicating whether the wait timed out.
And even then, you must beware of spurious wakeup (which is indistinguishable from a call to signal
.)
You should be using a loop as you currently are anyway, regardless of knowing whether the wait
timed out - partly due to the possibility of spurious wakeups. However, I'm not at all sure that you really need to know whether the call exited due to notification or not.
Consider the situation where the notification occurs a nanosecond before the timeout vs the situation where the notification occurs a nanosecond after the timeout. What's the useful difference between the two? Fundamentally there's a race condition if the two occur at "about the same time".
As far as I can tell, wait()
really doesn't let you tell whether the call timed out or not, but it shouldn't affect your code. You should be looping and testing something else that is a side-effect of the notification anyway.
It's not clear to me where a ThreadLocal
would come into play to be honest - that's exactly the opposite of what you want if you need to be able to tell from the waiting thread whether the notifying the thread has reached a certain point. I don't think you need an extra variable at all - your empty
is fine.
There's no direct way to report this with the builtin monitor API, but you could replace the wait()
and other functions with a new implementation that tracks this explicitly (untested):
private int wait_ct = 0, signal_ct = 0;
public void checkedNotifyAll() {
synchronized {
signal_ct = wait_ct;
notifyAll();
}
}
public void checkedNotify() {
synchronized {
signal_ct++;
if (signal_ct > wait_ct)
signal_ct = wait_ct;
notify();
}
// Returns true if awoken via notify
public boolean waitChecked(long timeout, int nanos) throws InterruptedException {
synchronized(this) {
try {
wait_ct++;
super.wait(timeout, nanos);
if (signal_ct > 0) {
signal_ct--;
return true;
}
return false;
} finally {
wait_ct--;
if (signal_ct > wait_ct) signal_ct = wait_ct;
notify(); // in case we picked up the notify but also were interrupted
}
}
// Note: Do not combine this with normal wait()s and notify()s; if they pick up the signal themselves
// the signal_ct will remain signalled even though the checkedWait()s haven't been
// awoken, potentially resulting in incorrect results in the event of a spurious wakeup
This isn't necessarily a good way to do this, of course; if you timeout just before notify()
is called, the signal condition may be lost, after all. You really should be waiting in a loop, checking some persistent condition.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With