CuriousMind
CuriousMind

Reputation: 15808

Are Java wait(), notify() 's implementation significantly different from locks?

Out of curiosity, when Java implements wait() and notify() methods, are they really just using locks? i.e., wait() acquires a mutex, notify() release a mutex, notifyAll() releases all mutexes (in the same object, of course)?

Other than being less cumbersome than using locks, are there other advantages of using wait() and notify()?

[EDIT] I realized what I confused myself about after Brian's comments:

wait doesn't lock, it releases the lock and passes it to someone else who's waiting on a synchronized statement for the mutex, then waits to be notified by someone else who has the lock and calls notify, which passes the lock back to the original thread that called wait. I think that's where you're getting confused. – Brian 17 mins ago

Upvotes: 8

Views: 3725

Answers (5)

selig
selig

Reputation: 4844

The other questions have focused on what the language says that wait and notify are - but that doesn't seem to be what your question is about... you talk about mutexes, which is an implementation detail and therefore JVM specific.

So we need to pick a JVM - let's pick openjdk (source available here). The bit of code that (ultimately) handles all this stuff is found at hotspot/src/share/vm/runtime/objectMonitor.cpp.

This maintains two datastructures - a wait set and an entry set. Waiting threads are added to the wait set and parked whereas threads attempting to take the monitor are added to the entry set and then parked. On notify a thread is taken from the wait set and added to the entry set. When a thread releases the lock it unparks a thread from the entry set if there is one. Note that these sets are actually implemented as queues (linked lists) so are treated on a FIFO basis.

Therefore, in this particular case the implementation treats waiting on an object's monitor and attempting to take an object's monitor in a similar way.

But this is just one implementation of one JVM (although it's likely that others do something similar) - so we cannot rely on it. So I suppose the question is why do you want to know? If it's just curiosity then look through the openjdk code, it's fascinating. If you plan on using this information in your code... don't.

UPDATE

I realise that saying "park" doesn't tell us much. The code that parks a thread is platform specific (and is implemented in an object called PlatformEvent, which ParkEvent extends). In the version of openjdk that I'm looking at the park code for linux can be found at hotspot/src/os/linux/vm/os_linux.cpp and this calls pthread_mutex_lock(_mutex)... so in answer to your question yes calling wait may take a mutex on my machine. Note that there's lots of stuff that happens above this which might prevent us getting to this point.

Upvotes: 14

Lokesh
Lokesh

Reputation: 7940

wait(), notify() always work along with Synchronization , so comparison can be between Locks and synchronization. There is big difference between Locks like RentrantLock, ReadWriteLock and Synchronization [block, methods].

  1. Locks dont use synchronization internally while wait(), notify() will need synchronization.

  2. You use Lock along with java.util.concurrent.locks.Condition, which efficiently enables conditional locking, this is quite tedious to implement with synchronization..

  3. You dont have any tryLock option with synchronization , you either take lock or wait. But with Lock interface you have the choice.

Upvotes: 1

Glen Best
Glen Best

Reputation: 23115

Out of curiosity, when Java implements wait() and notify() methods, are they really just using locks? i.e., wait() acquires a mutex, notify() release a mutex, notifyAll() releases all mutexes?

Sorry, but none of that quite right. :)

  • It is the synchronized keyword that obtains the monitor. i.e. this is a form of locking. NB: using java.util.concurrent.locks.Lock does something similar.
  • wait() causes the current thread to wait until either another thread invokes the notify() method or the notifyAll() method for this object, or a specified amount of time has elapsed. Nothing to do with locking - but can only call this method when the current thread current thread already own's this object's monitor (in a synchronized block/method)
  • notify() wakes up a single thread that is waiting on this object's monitor. Again, nothing to do with locking - but can only call this method when the current thread current thread already own's this object's monitor (in a synchronized block/method)

Upvotes: 1

jtahlborn
jtahlborn

Reputation: 53694

wait() and notify() don't do any monitor acquisition. as the javadoc for these methods state, the caller must have acquired the monitor before calling. in fact, wait() actually releases the monitor the caller acquired (although, i guess technically wait does do monitor (re)acquisition before finally returning).

Upvotes: 4

Brian
Brian

Reputation: 17329

wait releases the lock you already have with the intention of re-obtaining it at some point in the future after someone else calls notify. This is in addition to the locking mechanisms provided by synchronized. Basically, you use synchronized to obtain a lock, then you use wait, notify, and notifyAll to control how those locks are released and re-locked.

Upvotes: 1

Related Questions