Main thread creates child thread. Parent needs some work from child, but not all of it, so parent must wait until child finish that work (child will keep doing some other work).
I would like to achieve it with monitors so I coded the following:
public class WaitChildThreadMonitor {
public static final int TOTAL_COUNT_AMOUNT = 1_000;
static int count = 0;
class Child implements Runnable {
@Override
public void run() {
work();
}
public synchronized void work() {
letParentWaitForThis();
for (int i = 0; i < TOTAL_COUNT_AMOUNT; i++)
++WaitChildThreadMonitor.count;
this.notifyAll();
// More child work that parent doesn't need right now
// ...
for (int i = 0; i < TOTAL_COUNT_AMOUNT; i++)
++WaitChildThreadMonitor.count;
}
private void letParentWaitForThis() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
}
public synchronized void waitForWork() throws InterruptedException {
this.wait();
}
}
void main() throws InterruptedException {
Child child = new Child();
Thread childThread = new Thread(child);
// If the next two methods doesn't execute atomically,
// parent execution gets blocked forever
childThread.start();
child.waitForWork();
System.out.printf("Count value is %d\n", WaitChildThreadMonitor.count);
childThread.join();
}
public static void main(String[] args) throws InterruptedException {
(new WaitChildThreadMonitor()).main();
}
}
The problem is that if child executes "this.notifyAll()" after he finished his main work before parent executes "this.wait()" in "child.waitForWork()", parent won't get notified and will get blocked forever.
I tried to solve it forcing a context switch before child start his work using Thread.sleep() method. It doesn't seem to work as expected.
With sleep and without sleep, sometimes parent gets blocked and program never ends, sometimes it ends properly (I guess because parent waited before child notified).
How can I fix this?
Thanks in advance!
You must not call wait
if the thing you want to wait for has already happened. That's the reason the method that calls wait
is synchronized
-- so you can check the shared state that represents the thing you're waiting for.