Does Thread.join() release the lock? Or continue to hold it? - java

As I understand it, internally obj.join() calls wait(). This means that join() always releases the lock (because wait() always releases the lock after being called).
The API doc explains:
This implementation uses a loop of this.wait calls conditioned on
this.isAlive. As a thread terminates the this.notifyAll method is
invoked. It is recommended that applications not use wait, notify, or
notifyAll on Thread instances.
People here on SO say that join() does not release any lock because the API does not mention it explicitly. But this logic seems strange to me.
Here is the main logic from join()'s code:
while (isAlive()) {
wait(0);
}
This site further adds to the confusion (I think they are mistaken):
3) The third difference between the wait() and join() methods is that when a thread calls the wait() method it releases any lock held for the object on which wait() is called, but calling the join() method doesn't release any monitor or lock.

wait releases the monitor held on the object which wait is invoked on, but not any other monitors.
The current thread must own this object's monitor. The thread releases ownership of this monitor and waits [...].
In other words, given the following:
synchronized (a) {
synchronized (b) {
b.wait();
}
}
At b.wait(), the current thread releases b's monitor, but not a's monitor.
If t.join() is implemented using t.wait() internally, then t's monitor is released while waiting, but not any other monitor.
This join implementation is a case of leaky abstraction, by the way. If Thread used a private final Object monitor; to wait on instead, we could say that join released no monitors, even if it used wait internally without us knowing. There would be no reason to document the implementation detail of using wait, because the monitor would be inaccessible to us, so we would not need to know about it.
The reason that we know join uses wait internally is that the people who originally wrote the method chose a monitor which is accessible to us. This created the need to reveal the implementation details. join is not really supposed to release monitors from our perspective, just wait for a thread to complete, but an implementation was chosen which required us to know more about it than we should.

Though the excellent answer from #Radiodef clarifies & elaborates the leaky abstraction shortcoming, in simpler terms to answer #vrinchvucz confusion the answer is,
Yes, when a thread invokes t.join it does acquire and release 'a' monitor lock. That monitor lock is that of the thread t itself since the implementation of join method on Thread class implemented it by using this.wait inside of the synchronized join method which is the leaky abstraction issue that #Radiodef points to.
Thus unless the thread acquires the monitor lock of t itself before it invokes t.join we can say that NO client/user acquired monitor locks are released in the t.join invocation (because the monitor lock in question is NOT any that the client/user code acquired in the thread that invoked t.join).
This since as clearly stated in the docs for Object#wait
Note that the wait method, as it places the current thread into the
wait set for this object, unlocks only this object; any other objects
on which the current thread may be synchronized remain locked while
the thread waits.
Which is why the docs for Thread#join does not mention anything about locks being released while still giving the implementation details regarding the use of this.wait.

Related

What does it mean by waiting on object monitor [duplicate]

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.
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 the object does not own the object monitor when it calls Object.wait(), it will not be able to access the object to setup a notify listener until the the monitor is released. Instead, it will be treated as a thread attempting to access a method on a synchronized object.
Or to put it another way, there is no difference between:
public void doStuffOnThisObject()
and the following method:
public void wait()
Both methods will be blocked until the object monitor is released. This is a feature in Java to prevent the state of an object from being updated by more than one thread. It simply has unintended consequences on the wait() method.
Presumably, the wait() method is not synchronized because that could create situations where the Thread has multiple locks on the object. (See Java Language Specifications/Locking for more info on this.) Multiple locks are a problem because the wait() method will only undo one lock. If the method were synchronized, it would guarantee that only the method's lock would be undone while still leaving a potential outer lock undone. This would create a deadlock condition in the code.
To answer your question on Thread.sleep(), Thread.sleep() does not guarantee that whatever condition you are waiting on has been met. Using Object.wait() and Object.notify() allows a programmer to manually implement blocking. The threads will unblock once a notify is sent that a condition has been met. e.g. A read from disk has finished and data can be processed by the thread. Thread.sleep() would require the programmer to poll if the condition has been met, then fall back to sleep if it has not.
It needs to own the monitor, since the purpose of the wait() is to release the monitor and let other threads obtain the monitor to do processing of their own. The purpose of these methods (wait/notify) is to coordinate access to synchronized code blocks between two threads that require each other to perform some functionality. It is not simply a matter of making sure access to a data structure is threadsafe, but to coordinate events between multiple threads.
A classic example would be a producer/consumer case where one thread pushes data to a queue, and another thread consumes the data. The consuming thread would always require the monitor to access the queue, but would release the monitor once the queue is empty. The producer thread would then only get access to write to the thread when the consumer is no longer processing. It would notify the consumer thread once it has pushed more data into the queue, so it can regain the monitor and access the queue again.
Wait gives up the monitor, so you must have it to give it up. Notify must have the monitor as well.
The main reason why you want to do this is to ensure that you have the monitor when you come back from wait() -- typically, you are using the wait/notify protocol to protect some shared resource and you want it to be safe to touch it when wait returns. The same with notify -- usually you are changing something and then calling notify() -- you want to have the monitor, make changes, and call notify().
If you made a function like this:
public void synchWait() {
syncronized { wait(); }
}
You would not have the monitor when wait returned -- you could get it, but you might not get it next.
Here's my understanding on why the restriction is actually a requirement. I'm basing this on a C++ monitor implementation I made a while back by combining a mutex and a condition variable.
In a mutex+condition_variable=monitor system, the wait call sets the condition variable into a wait state and releases the mutex. The condition variable is shared state, so it needs to be locked to avoid race conditions between threads that want to wait and threads that want to notify. Instead of introducing yet another mutex to lock its state, the existing mutex is used. In Java, the mutex is correctly locked when the about-to-wait thread owns the monitor.
Mostly wait is done if there is a condition say a queue is empty.
If(queue is empty)
queue.wait();
Let us assume the queue is empty.
In case if the current thread pre-empts after checking the queue, then if another
thread adds few elements to queue, the current thread will not know and will go for wait
state. Thats wrong.
So we should have something like
Synchornized(queue)
{
if(queue is empty)
queue.wait();
}
Now let us consider what if they made wait itself as synchronized. As already mentioned in one of the comments, it releases only one lock. That means if wait() was synchronized in the above code only one lock would have been released. Implies that current thread will go for wait with the lock for the queue.

using Intrinsic Locks in SYNCHRONIZATION

Suppose d is the object we're using to invoke wait. When a thread invokes d.wait, it must own the intrinsic lock for d — otherwise an error is thrown. Invoking wait inside a synchronized method is a simple way to acquire the intrinsic lock.
so is this means that two threads cannot invoke wait() at the same time? what do intrinsic lock here mean [mentioned it as Monitor]? but how 's monitor implemented to achive mutual exclusion?
once the thread invokes wait does it holds object forever?
if so how about other thread using that lock for notifyAll()?
if we need to acquire object during notifyall, then why all waiting threads notified?
shouldn't it notify threads waiting on that object alone?
Any code to explain is appreciated.
so is this means that two threads cannot invoke wait() at the same
time?
Correct two thread cannot invoke wait() at the same time. However, once one thread is in wait(), another thread can acquire the same lock and enter a wait() state soon after. You can have any number of threads WAITING on the same object, but only one really holds the lock.
what do intrinsic lock here mean [mentioned it as Monitor]? but
how 's monitor implemented to achive mutual exclusion?
Only one thread can be running while holding a object. Other thread can be blocking trying to acquire the lock and more can be wait()ing on it.
once the thread invokes wait does it holds object forever?
The opposite, it gives it up or another thread can acquire it almost immediately.
if so how
about other thread using that lock for notifyAll()?
If you call notifyAll() on the object, all the wait()ing thread are woken in turn. Those threads can only acquire the lock one at a time and will re-acquire the lock as soonas they can.
if we need to acquire object during notifyall, then why all waiting
threads notified?
That is what notifyAll does, it is considered safer than using notify, which wakes a random one as it is less prone to coding errors.
shouldn't it notify threads waiting on that object alone?
That is what it does.
You should note that;
before you notify()/notifyAll() you should perform a state change. You should also wait() inside a loop which checks that state change. You need to do this because a) wait() can miss a notify(), b) it can wake spuriously c) another thread might grab whatever you ahve done and it might need to wait again.
over the last 9 years, there has been greater use of High Level concurrency classes. Using these classes mean you don't need to work with Threads, Queues, wait() and notify() directly.
Invoking wait inside a synchronized method is a simple way to acquire
the intrinsic lock.
Wait does not provide the lock on an object rather it makes the thread to wait to listen about the lock release when other thread calls notify. Thread gets the lock when it enters the guarded//synchronized block. Synchronzied block/method allows to take the lock if available otherwise thread cannot enter those code block.
Locks are not held forever, according to the javadoc:
The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.
When you call wait(), you release the intrinsic lock on that object, until another thread calls notify() or notifyAll() on it. At that point, the JVM will wake one of the threads waiting, and automatically reacquire the lock on that object.
So to answer your question, yes, multiple threads can wait() on the same object.

Does the Java JVM guarantee the correct "wait" will be notified when calling "notify"?

According to a colleague, JVM does not guarantee that when calling "notify" on an object, the correct "wait" will be notified at that time. He says there can be a case when a previous notify which is not valid anymore is delivered at an invalid time.
Is this true? If so, how/why is this, and what use is the wait/notify mechanism if you cannot assume something as basic as this will work?
For java.lang.Object.notify, The Javadoc says:
Wakes up a single thread that is waiting on this object's monitor. If
any threads are waiting on this object, one of them is chosen to be
awakened. The choice is arbitrary and occurs at the discretion of the
implementation. A thread waits on an object's monitor by calling one
of the wait methods.
Here is a pattern to wait for a particular condition:
synchronized( lock ) {
while( conditionEvaluation( data )) {
lock.wait();
}
}
The counterpart should use java.lang.Object.notifyAll() to ensure the vivacity of the application. Even if today, it's only one waiter, after many evolutions of the software, it may be several waiters in the future, so notifyAll() is more robust than notify().
Each object that waits on an intrinsic lock will enter the lock's wait set. When you invoke notify on the lock object, one of the threads in its wait set will be chosen to resume work. The only guarantee that the JVM offers is that the waiting threads will be eventually notified. One of the main reasons for this non-deterministic behavior is the way suspended threads are chosen to run by the JVM, which is arbitrary. In addition however, locks in java implement a non-fair locking policy which permits thread barging. This simply means that it is permissible for new lock requests to jump ahead of the lock's wait set, it the lock is available at the time of the request. The justification behind this is that given substantial contention, there might be some (potentially significant) delay before choosing and resuming a suspended thread in the wait set and the time it actually runs. Any incoming lock request from a thread could therefore utilize this time delay to immediately run, in the hope that it will have released the lock by the time the resumed thread is ready to run. For example consider the following sequence of events:
Thread A that previously has acquired monitor X calls notify()
Thread B waiting on monitor X has chosen to be suspended (arbitrarily).
Thread C tries to acquire monitor X, sees that it is available and acquires it.
Thread C runs (despite thread B is currently in the process of being resumed)
Thread C finishes execution and releases monitor X, just before thread B is actually run.
Thread B is ready to run so it acquires the lock and starts execution.
It should be evident that between step 2 and 6 there exists some time interval where no threads are actually using the lock. Thread C barges in and utilizes the time interval as an optimization. The downside of this of course is the risk of not releasing the lock at the time thread B is ready to run, which at that time thread B will notice that the lock is unavailable and will enter the wait set again. Statistically however it can be proven that non-fair locking offers better performance in most situations.
As an aside note, you could use fair locks where waiting threads are resumed in the order they acquired the lock, but in practice this offers worse performance. Read more about this here: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html
I hope this answers your question.
No it's not true. When a thread invokes notify, one waiting thread is awakened (if such a thread exists, otherwise notification is lost). Probably your colleague had in mind "spurious notify", which can awake a thread when in fact no other thread invoked notify or notifyAll. To filter "spurious notify", each notify invocation should accompanied with some change in monitored object state, and the waiting threads should check that state:
synchronized void up() {
counter++;
notify();
}
synchronized void down() {
while (counter==0) {
wait();
}
counter--;
}
Note checking state in down() is done before call to wait(), as it could be changed before the invocation and the notification is lost. In other words, the real information is passed with object's state, and wait/notify only help to avoid polling. Never rely on notifications without changing an object's state.

what does WAKEUP really mean in the notify/notifyall context?

some comments here have confused me! I thought I knew this and god knows I've written a ton of MT code, but its been a while and so....
FWIK notify/notifyall
notify: one thread is selected from the waitset and moved to the entryset to acquire monitor lock
notifyall : all threads are "notified" -
are they all moved to the entryset ?
Does this mean that they will all reacquire the lock as the lock holder releases it ? no more notify necessary ?
-all answers are just rephrasing what I've read elsewhere. I understand that only one of them can acquire the lock etc., my question this: once a thread is notified, it gets to wait on the monitor. right ? so need not be notified again if the thread holding the lock calls notify
For a precise specification of what happens, refer to the JLS section 17.8.2.
When a thread performs a notifyAll on a lock object, all other threads that are currently waiting are removed from the lock's waitset; i.e. they become runable. Each one then tries to reacquire the lock, and when that succeeds it returns from the wait(...) call.
Of course, the threads only succeed in acquiring the lock one at a time, and there are no guarantees of fairness. But eventually, they will all have acquired the lock.
Notification of waiting threads occur when notifyAll is called. All the waiting threads are removed from the object's wait set. Only one of the thread in the wait set is selected, of which there is no guarantee as to which thread is selected
The langspec has a section on Thread Notification
When notifyAll is called, all threads waiting on that lock are woken up, and one of them acquires the lock. The rest goes back to wait.
This may sound like notifyAll is a waste of resources, but AFAIR there used to be special tricky cases when calling notify may wake up the wrong thread, which can not handle the situation, resulting in a deadlock. Therefore it was recommended to use notifyAll always.
Since Java5 it is rarely necessary to worry about things like this, because the new concurrency utilities almost always handle these tasks better than wait and notify*, rendering them almost obsolete. The typical use of wait and notify* is in blocking queues, and now we have several ready made implementations of these - such as LinkedBlockingQueue and PriorityBlockingQueue - available in the class library.

Why are wait() and notify() declared in Java's Object class?

Why are the wait() and notify() methods declared in the Object class, rather than the Thread class?
Because, you wait on a given Object (or specifically, its monitor) to use this functionality.
I think you may be mistaken on how these methods work. They're not simply at a Thread-granularity level, i.e. it is not a case of just calling wait() and being woken up by the next call to notify(). Rather, you always call wait() on a specific object, and will only be woken by calls to notify on that object.
This is good because otherwise concurrency primitives just wouldn't scale; it would be equivalent to having global namespaces, since any calls to notify() anywhere in your program would have the potential to mess up any concurrent code as they would wake up any threads blocking on a wait() call. Hence the reason that you call them on a specific object; it gives a context for the wait-notify pair to operate on, so when you call myBlockingObject.notify(), on a private object, you can be sure that you'll only wake up threads that called wait methods in your class. Some Spring thread that might be waiting on another object will not be woken up by this call, and vice versa.
Edit: Or to address it from another perspective - I expect from your question you thought you would get a handle to the waiting thread and call notify() on that Thread to wake it up. The reason it's not done this way, is that you would have to do a lot of housekeeping yourself. The thread going to wait would have to publish a reference to itself somewhere that other threads could see it; this would have to be properly synchronized to enforce consistency and visibility. And when you want to wake up a thread you'd have to get hold of this reference, awaken it, and remove it from wherever you read it from. There's a lot more manual scaffolding involved, and a lot more chance of going wrong with it (especially in a concurrent environment) compared to just calling myObj.wait() in the sleeping thread and then myObj.notify() in the waker thread.
The most simple and obvious reason is that any Object (not just a thread)
can be the monitor for a thread. The wait and notify are called on the
monitor. The running thread checks with the monitor. So the wait and notify methods are in Object and not Thread
Because only one thread at a time can own an object's monitor and this monitor is what the threads are waiting on or notifying. If you read the javadoc for Object.notify() and Object.wait() it's described in detail.
The mechanism of synchronization involves a concept - monitor of an object. When wait() is called, the monitor is requested and further execution is suspended until monitor is acquired or InterruptedException occurs. When notify() is called, the monitor is released.
Let's take a scenario if wait() and notify() were placed in Thread class instead of Object class. At one point in the code, currentThread.wait() is called and then an object anObject is accessed.
//.........
currentThread.wait();
anObject.setValue(1);
//.........
When currentThread.wait() is called, monitor of currentThread is requested and no further execution is made until either the monitor is acquired or InterruptedException occurs. Now while in waiting state, if a method foo() of another object anotherObject residing in currentThread is called from another thread, it is stuck even though the called method foo() does not access anObject. If the first wait() method was called on anObject, instead of the thread itself, other method calls (not accessing anObject) on objects residing in the same thread would not get stuck.
Thus calling wait() and notify() methods on Object class(or its subclasses) provides greater concurrency and that's why these methods are in Object class, not in Thread class.
A few of the other answers use the word "monitor", but none explain what it means.
The name "monitor" was coined way back in the 1970s, and it referred to an object that had its own intrinsic lock, and associated wait/notify mechanism. https://en.wikipedia.org/wiki/Monitor_%28synchronization%29
Twenty years later, there was a brief moment in time when desktop, multi-processor computers were new, and it was fashionable to think that the right way to design software for them would be to create object-oriented programs in which every object was a monitor.
Turns out not to have been such a useful idea, but that brief moment happens to be exactly when the Java programming language was invented.
Read here for an explanation of wait and notify.
It would be better to avoid these however in your applications and use the newer java.util.concurrent package.
I will put it in a simple way:
To call wait() or notify() you need to own the object monitor - this means wait() or notify() needs to be present in the synchronized block
synchronized(monitorObj){
monitorObj.wait() or even notify
}
Thats the reason these methods are present in object class
This is because,these methods are for inter thread communication and interthreadcommunication happens by using locks, but locks are associated with objects.hence it is in object class.
Wait and Notify methods are used communication between two Threads in Java. So Object class is correct place to make them available for every object in Java.
Another reason is Locks are made available on per Object basis. Threads needs lock and they wait for lock, they don't know which threads holds lock instead they just know the lock is hold by some thread and they should wait for lock instead of knowing which thread is inside the synchronized block and asking them to release lock

Categories

Resources