notify() vs notifyAll()

Obviously since I'm here I have my SCJP cert so I know what the difference between the two is BUT I'm still not quite clear on when it is appropriate to use which.

My unlocking method for the B&S assignment looks something like the following. (approximately as I don't actually have the source to hand!)

As there may be many threads waiting for the locked object, would it be appropriate to use notifyAll() here? Or can I rely on each thread getting the lock eventually and releasing it when it is done?

I have tested the lock/unlock methods using 1000 threads and only 4 available record numbers and it worked ok (took a long time to finish!) but I'm not sure if I'm missing something?

This may be obvious to you but my Java concurrency experience begins and ends with what was required for the programmer exam.

Cheers

David

Ulf Dittmer

Rancher

Posts: 42969

73

posted 9 years ago

This thread -coincidentally named exactly the same as this one- gives a good overview of the issues involved.

David A. Scott

Ranch Hand

Posts: 55

posted 9 years ago

heh - thanks.

I thought I'd done a reasonable search.

David A. Scott

Ranch Hand

Posts: 55

posted 9 years ago

So I think this comment from Henry Wong seems to cover what I'm talking about. Releasing the lock in my case can only possibly satisfy the needs of a single thread (at a time) so I am right to stick with notify().

Anyone have any further comments?

IMHO, whether you call notify() or notifyAll() is dependant on the state that you just changed. If you changed the state, in a manner that can satisfy one waiting thread, then you call notify. If you change the state that can satisfy multiple waiting threads -- like releasing a group of semaphores, or shutting down the system (special case) -- then you call notifyAll().

I don't think it matters if you have one waiting thread, many waiting threads, or even zero waiting threads. You should design your application in a fashion where you actually don't care how many threads are waiting, if there are even any. This is why you should also (1) check the state prior to waiting, and (2) check again after waiting.

Petr Hejl

Ranch Hand

Posts: 68

posted 9 years ago

It depends on behaviour of your lock method. What happens if you unlock record 1 and the thread that jvm will choose for wake up (through notify) will be waiting for record 2? It could cause a deadlock...

David A. Scott

Ranch Hand

Posts: 55

posted 9 years ago

Originally posted by Petr Hejl: It depends on behaviour of your lock method. What happens if you unlock record 1 and the thread that jvm will choose for wake up (through notify) will be waiting for record 2? It could cause a deadlock...

My lock/unlock method is synchronized on a HashMap which acts as a lookup of locked records (and their associated cookies).

The way I see it working :-

Thread 1 Successfully Locks record 10 Thread 2 Attempts to Lock record 10 but can't so it wait()'s Thread 3 Attempts to Lock record 20 but can't so it wait()'s Thread 1 Unlocks record 10 and issues a notify()

At this point EITHER - Thread 2 gets the lock on record 10 OR Thread 3 gets the lock on record 20.

If it is the latter I am presuming that the notify() Thread 3 issues will release the wait() on thread 2? Am I being naive? [ February 28, 2007: Message edited by: David A. Scott ]

Originally posted by Petr Hejl: It depends on behaviour of your lock method. What happens if you unlock record 1 and the thread that jvm will choose for wake up (through notify) will be waiting for record 2? It could cause a deadlock...

Agreed. For notify() to work properly, the threads that are waiting should be waiting for the same resource / event -- as it is not possible to choose which thread to wake up.

So a straight swith from notify() to notifyAll() would remedy this because each waiting thread would be notfied?

If you have threads waiting on the same object for different conditions, changing notify() to notifyAll(), is probably the easiest and quickest remedy to implement -- although probably not the best.

Another option is to look at the ReentrantLock class (assuming that you have Java 5). It implements a basic mutex, which is similar to Java synchronization mechanism. It also has a method that returns a Condition variable which is similar to Java wait and notify mechanism.

The interesting part of this class, is that you can call the method to get as many condition variables as you want. Basically, you can get a bunch of different objects to use to wait on conditions (AKA condition variables) -- condition variables that share the same mutex.