Signalling between threads in Java

Various releases of Java have introduced more sophisticated concurrency patterns to Java. You don’t need to build your own thread pooling techniques, or queues between threads. However, for a lot of uses, the synchronized keyword is pretty much all you need.

I had a recent use case, for which it seemed that there wasn’t a sophisticated library class, nor was a single line of code enough. I wanted an object on one thread to be able to signal when it was done and for other threads to be able to block until that signal was made.

This is not that difficult to do, but you can’t just do this:

private Object event = new Object();

// for consumers to use to wait for the event
public void waitForEvent() {
    // to do a wait, we need to acquire the monitor
    synchronized(object) {
        // wait until object notifies - which relinquishes the lock on the object too
        object.wait();
    }
}

private void signalEvent() {
    synchronized(object) {
        // release all waiters
        object.notifyAll();
    }
}

The above, which illustrates the synchronization pattern for notify and wait in Java, isn’t quite enough. The reason it’s not enough is that in concurrent processing, it’s possible for the event to be signalled before the waiting thread calls waitForEvent. If the event has already been signalled, and you start waiting for a notify that never comes, then you’re blocked either forever or until a timeout.

Reading up on the subject, it seems it’s common to put some sort of boolean alongside this pattern.

Furthermore, it turns out that wait can abort spuriously without being notified, so if you’re not checking a boolean in a while loop, you may wake up early and be in an error state. This code needs taming!

My next advice. Object orientation ALWAYS helps with thread safety stuff in Java. I created a Signal class, whose job is to store the signal and allow callers to wait for it.

I’ve shared this code here on GitHub. Feel free to copy it and use it as you wish.

Here’s a snippet:

public class Signal {
    private boolean signalled = false;
	
    /**
      * Set the done flag
      */
    public synchronized void setSignal() {
        signalled = true;
        notifyAll();
    }

    // ... other stuff

     /**
       * Wait indefinitely for the done signal
       * @throws InterruptedException on thread error
       */
     public synchronized void waitForSignal() throws InterruptedException {
         while (!signalled) {
              wait();
         }
     }
}

What’s quite nice about this is that the object orientedness of it means it’s easily synchronized with the function level synchronized keyword – when you synchronize a function, that makes the whole containing object lock for the duration of the synchronization. Using this signal is very easy – it just acts like a flag, but you can wait for it as well as read it.

The following unit test (also in GitHub) shows how the signal makes it easy for threads to set gates on each other. Note that the final signal in this example could have been done with thread.join(), but wasn’t for the purposes of the test. Also, note how Junit’s @Test(timeout= ) syntax is used to ensure that the test which is running waiting threads, doesn’t go on forever owing to a bug.

	@Test(timeout=TIMEOUT)
	public void interThreadSignalling() throws InterruptedException {
		final Signal threadStarted = new Signal();
		final Signal threadAllowedToProceed = new Signal();
		final Signal threadFinished = new Signal();
		
		Thread thread = new Thread(new Runnable(){

			@Override
			public void run() {
				// set that we've started
				threadStarted.setSignal();
				
				// wait until we're allowed to proceed
				try {
					threadAllowedToProceed.waitForSignal();
				} catch (InterruptedException e) {
					// do nothing here
				}
				
				// signal we've finished
				threadFinished.setSignal();
				
			}
			
		});
		
		thread.start();
		
		// wait for the thread to have started
		threadStarted.waitForSignal();
		
		// thread should not have finished - so wait to see if it has and check it hasn't
		threadFinished.waitForSignal(SHORT_TIME);
		assertFalse(threadFinished.isSignalled());
		
		// then signal the thread to finish
		threadAllowedToProceed.setSignal();
		
		// then wait indefinitely for the thread to say it's finished
		threadFinished.waitForSignal();
		
		// reaching here before the overall timeout is proof that the signalling works between threads
	}

Hope this is useful to someone.

Advertisements

2 comments

  1. This is a nice solution, but if you just need to wait for another thread to finish, then using CountDownLatch might be simpler.

    • CountDownLatch has its place, though what could be simpler than just waiting for an event 🙂

      In the use case I faced, I had multiple threads to block until a single event had occurred.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s