[concurrency-interest] When do you use wait/notify?

Gregg Wonderly gregg.wonderly@pobox.com
Mon, 26 Jan 2004 09:12:42 -0600

Doug Lea wrote:

> Ernst's mail prompted me to also send this, which I've been meaning to
> do for a while:
> We'd like to know, given what is in JSR166, what kinds of cases might
> still arise where application writers will use error-prone code
> involving especially wait/notify rather than higher-level
> constructions.

I have many applications that utilize queues and worker threads.
I will use wait() and notify() to tell the workers that the containers
have stuff to do in them.  As part of my attempts to avoid synchronizing 
everywhere, I will typically have the worker threads call wait(timeout)
so that they can inspect the state of the world occasionally without 
notify having to be called.  This keeps missing notifies from causing 
the system to misbehave. It also allows work to be handled in bursts 
based on timeouts that I can change at runtime to tune the system's 
performance.  Finally, it allows debugging messages to be provided that 
tell me that those worker threads are still active.  And, when notify is 
used by the thread adding the work item, the workers can respond 
immediately if they are idle.

I typically do not use outward visible or container references in my 
wait() and notify() calls related to work notification.  This is done to 
keep circular references from getting in the way.  But, primarily, I try 
to design the synchronization so that it is minimized.  I do tend to use 
Vector and Hashtable for my containers so that I get atomic access to 
the mutation of the container without having to explicitly assert the 
synchonization which can be a source of bugs in and of itself.

My most heavily threaded applications do around 30 transactions a second 
with around 60 threads running simultaneously.  I've tuned these 
applications over the years by using SIGQUIT on unix to force a thread 
dump.  I then look at what synchronization is most visible.  I go back 
and revisit those areas of the code and try to establish whether the 
synchronization is necessary, or if the amount of work in the 
synchronized section can be minimized.

This is an indispensible feature that I understand will be 
programatically accessible in 1.5.