Someone at work just asked for the reasoning behind having to wrap a wait inside a synchronized.
Honestly I can't see the reasoning. I understand what the javadocs say--that the thread needs to be the owner of the object's monitor, but why? What problems does it prevent? (And if it's actually necessary, why can't the wait method get the monitor itself?)
I'm looking for a fairly in-depth why or maybe a reference to an article. I couldn't find one in a quick google.
Oh, also, how does thread.sleep compare?
edit: Great set of answers--I really wish I could select more than one because they all helped me understand what was going on.
In concurrent programming, a monitor is a synchronization construct that allows threads to have both mutual exclusion and the ability to wait (block) for a certain condition to become false. Monitors also have a mechanism for signaling other threads that their condition has been met.
That is the point in the monitor, is only one thread can be executing in it at a time; so if one is executing in it, subsequent ones attempting to enter must wait for it to leave.
wait() causes current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0). The current thread must own this object's monitor.
Working: In java, synchronized methods and blocks allow only one thread to acquire the lock on a resource at a time. So, when wait() method is called by a thread, then it gives up the lock on that resource and goes to sleep until some other thread enters the same monitor and invokes the notify() or notifyAll() method.
Lots of good answers here already. But just want to mention here that the other MUST DO when using wait() is to do it in a loop dependent on the condition you are waiting for in case you are seeing spurious wakeups, which in my experience do happen.
To wait for some other thread to change a condition to true and notify:
synchronized(o) { while(! checkCondition()) { o.wait(); } }
Of course, these days, I'd recommend just using the new Condition object as it is clearer and has more features (like allowing multiple conditions per lock, being able to check wait queue length, more flexible schedule/interrupt, etc).
Lock lock = new ReentrantLock(); Condition condition = lock.newCondition(); lock.lock(); try { while (! checkCondition()) { condition.await(); } } finally { lock.unlock(); }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With