Why can't the Boolean flag also be used as wait () / notifyAll () mutex?

I have a long runnable. It performs a large number of iterations inside the while loop in its run () function. I need functionality to pause and resume runnable, which I implemented with volatile Boolean pauseFlag, which can be set by another thread.

Once Runnable has detected that pauseFlag- true, it calls pauseFlag.wait()to pause its execution. Resume is done by setting pauseFlagto false, and then calling pauseFlag.notifyAll().

Thus, it pauseFlagacts as a flag and mutex. However, this combined functionality does not work. Runnable retains the lock pauseFlag.wait()indefinitely.

If I create a separate mutex, say, Object mutex = new Object();and use mutex.notifyAll()/ mutex.wait(), but when used pauseFlagas a boolean flag, Runnable behaves as intended.

The non-working code is shown below:

public class PausableRunnable implements Runnable
{
    private boolean done;

    private volatile Boolean pauseFlag = false;

    /** Pause execution. This is an asynchronous (non-blocking) call. */
    public void pause() // <-- called by another thread
    {
        pauseFlag = true;
    }

    /** Resume execution */
    public void resume() // <-- called by another thread
    {
        pauseFlag = false;
        synchronized (pauseFlag)
        {
            pauseFlag.notifyAll();
        }
    }

    @Override
    public void run()
    {
        try
        {
            while (!done && !Thread.currentThread().isInterrupted())
            {
                while (pauseFlag)
                {
                    synchronized (pauseFlag)
                    {
                        // Pause flag was set. Suspend until we are notified that we can continue
                        pauseFlag.wait();
                    }
                }
                // execute our main behaviour. set done = true when done iterating.
                // ....
            }
        } catch (InterruptedException e)
        {
            Thread.currentThread().interrupt();
        }
    }
}

So, although I found a solution using a separate object, I would like to understand the problem. Why does this implementation fail?

+4
source share
1 answer

I made the same mistake.

wait/ notifyworks on an object, not a link

When you change the object referenced

private volatile Boolean pauseFlag

wait - . ( , , TRUE FALSE, , )

final, wait/notify.

+8

All Articles