I have a thread that updates it's state from time to time and I want a second thread to be able to wait for the first thread to be done. Something like this:
Thread 1: while(true) { ...do something... foo.notifyAll() ...wait for some condition that might never happen... ... } Thread 2: ... foo.wait(); ...
Now this looks nice and all unless Thread 1's notifyAll() runs before Thread 2's wait(), in which case Thread 2 waits until Thread 1 notifies again (which might never happen).
My possible solutions:
a) I could use a CountDownLatch or a Future, but both have the problem that they inherently only run once. That is, in Thread 1's while loop, I would need to create a new foo to wait for each time and Thread 2 would need to ask which foo to wait for. I have a bad feeling about simply writing
while(true) { foo = new FutureTask(); ... foo.set(...); ...wait for a condition that might never be set... ... }
as I fear that at foo = new FutureTask(), what happens when someone waited for the old foo (for "some reason", set was not called, e.g. a bug in the exception handling)?
b) Or I could use a semaphore:
class Event { Semaphore sem; Event() { sem = new Semaphore(1); sem . } void signal() { sem.release(); } void reset() { sem.acquire(1); } void wait() { if (sem.tryAcquire(1)) { sem.release(); } } }
But I fear that there is some race condition, if multiple threads are wait()ing for it while another one signal()s and reset()s.
Question:
Is there nothing in the Java API that resembles the Windows Event behaviour? Or, if you despise Windows, something like golang's WaitGroup (i.e. a CountDownLatch that allows countUp())? Anything?
How to do it manually:
Thread 2 cannot simply wait because of spurious wakeup and in Java there is no way to know why Object.wait() returned. So I need a condition variable that stores whether the event is signalled or not. Thread 2:
synchronized(foo) { while(!condition) { foo.wait(); } }
And Thread 1 of course sets condition to true in a synchronized block. Thanks to weekens for the hint!
Is there an existing class that wraps that behaviour?
Or do I need to copy and paste the code all over?
wait() causes current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0).
Working: In java, synchronized methods and blocks allow only one thread to acquire the lock on a resource at a time. So, when wait() method is called by a thread, then it gives up the lock on that resource and goes to sleep until some other thread enters the same monitor and invokes the notify() or notifyAll() method.
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 wait function doesn't release "all locks", but it does release the lock associated with the object on which wait is invoked.
It is standard practice to change some state when performing notifyAll and to check some state when performing wait().
e.g.
boolean ready = false; // thread 1 synchronized(lock) { ready = true; lock.notifyAll(); } // thread 2 synchronized(lock) { while(!ready) lock.wait(); }
With this approach, it doesn't matter if thread 1 or thread 2 acquires the lock first.
Some coding analysis tools will give you a warning if you use notify or wait without setting a value or checking a value.
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