using Intrinsic Locks in SYNCHRONIZATION - java

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.

Related

Why do we need notify() for inter thread communication

From the JAVA docs for Object notify()
The awakened thread will not be able to proceed until the current
thread relinquishes the lock on this object.
This means that unless the Thread which notifes, its synchronized block is complete and it releases the lock, the waiting thread cannot proceed. If that's the case then whats the point of having notify() if the sync block is going to be executed anyway? What's the actual use of notify() if it doesn't wake up the waiting thread and let it do its job?
Good question. Will point you to take a look at the Thread State Class.
A thread that calls the Object.notify method enables a thread that previously called Object.wait is now enabled to be scheduled by the thread scheduler. In parlance, the thread that was waiting is now "runnable". Although it is "runnable", it is not "running".
It can only continue running when the thread invoking notify releases the lock - one way is when it exits out of the synchronized block.
There are a lot of schematics on the web on the Thread States. Some of them are completely incorrect or confusing since they introduce terminology not in the official docs. Here is one that makes sense to me.
Strictly speaking, we don't: we could have the waiting thread run a loop where it re-acquires the lock, checks the condition, and sleeps for a short amount of time. But using wait() and notify() is much more efficient, because then the waiting thread doesn't keep waking up and tying up CPU (and tying up the lock).
notify() and notifyAll() are used to wake up thread(s) that called wait() on the same object on which notify() or notifyAll() is called.
Without call to notify() those "waiting" threads will wait forever (although JVM spec says that threads may sometime wake up without call to notify).
Also because call to notify() doesn't releases the lock associated with the object itself that call usually is the last statement in a synchronized block.
So notify() is used together with wait() and not by itself.
Usually the use case is like the following (blocking queue with limited size).
Method that adds element to queue (some pseudo code)
synchronized(lockObject) {
if (size < LIMIT) {
addElement();
lockObject.notifyAll(); //notifying threads that are waiting to get element from empty queue
} else {
lockObject.wait(); // waiting for other thread to get element from queue and make room for new element
}
}
Method that gets element
synchronized(lockObject) {
if (size > 0) {
getElement();
lockObject.notifyAll(); // notify threads that there is a room for new element
} else {
lockObject.wait(); // waiting for other thread to put element into the queue
}
}
Also calling lockObject.wait() releases lock on lockObject. More details regarding that could be found here: Java : Does wait() release lock from synchronized block
Notifying is what wakes up a thread that is waiting. If you remove the notify then waiting threads stay waiting (barring spurious wakeups but let’s not go there for now).
(Interrupting wakes up the thread but the guidance is to use it for cancellation only. Interruption targets a specific thread, where notifying lets the scheduler decide which threads are affected.)
When a thread calls wait it has to have the lock, then the wait method lets go of the lock.
When a thread calls notify it has to have the lock.
As a practical matter the notify can’t take effect on any waiting thread until the notifying thread relinquishes the lock. The first thing the notified thread is going to need to do anyway is to try to acquire the lock. All the passage you're quoting is trying to say is that the wakeup doesn't occur instantaneously when a thread calls notify.
So what happens here is that the notifying thread lets go of the lock and sends the notify to the scheduler, the scheduler decides which thread to notify, then the notified thread wakes up and contends for the lock in order to leave the wait method.
Imagine if you need a thread to wait for another thread to do something that it may or may not even currently be actively working on. For example, a thread that's waiting for a job to do may need to wait until another thread has put a job on the list of jobs it should do if that list is empty. How would you do this?
You can't just use some form of mutual exclusion. There may be long periods of time when there's no work to do and not thread holds any lock on the queue. There may just not be any work to do right now. The thread that does work needs to wait, without holding any lock, until another thread has given it some work to do.
So somewhere, there's a thread that does something like this:
Acquire the lock that protects some shared state that another thread might be waiting for a change to. (In this case, the job queue.)
Change the shared state to reflect the fact that the thing a thread might need to wait for has happened. (That is, put a job on the queue.)
Release the lock and let any waiting thread(s) know that the thing has happened.
So what could our code to wait look like? Perhaps:
Acquire the lock that protects the shared state.
Check whether we need to wait or not. (Is there a job on the queue?)
If we need to wait, wait. (If not, wait for a job to be placed on the queue.)
...
Oops, we have a problem. The thing we're waiting for can't happen because we hold the lock. No other thread can change the shared state. (Our thread to put a job on the queue can't touch the queue until we release the lock we acquired in step 1.)
Let's try it again:
Acquire the lock that protects the shared state.
Check whether we need to wait or not. (Is there a job on the queue?)
If we don't need to wait, exit this algorithm. (If there's a job, take it off the queue, release the lock, and do it.)
Release the lock. (So another thread can put a job on the queue.)
Wait for the thing to happen.
...
Oops, we have another problem. What if the thing we're waiting for happens after step 4 but before step 5. Since the lock has been released, the thing we're waiting for can happen. We can't check again because we don't hold the lock. How can we ensure we don't wait for something that has already happened, which may mean waiting forever?
To solve this, we need an atomic "unlock and wait" operation. That's what wait does. And we also need some operation that can end this wait that can be called by the thread that changed the shared state so that we no longer need to wait. That's what notify does.

What is happening when calling wait() method

I read in a Java textbook the following pertaining to multi-threading.
For a thread to call wait() or notify(), the thread has to be the owner of the lock for that object. When
the thread waits, it temporarily releases the lock for other threads to use, but it will need
it again to continue execution.
I'm confused about what is meant by the clause
When the thread waits, it temporarily releases the lock for other
threads to use
I don't get what that clause is talking about. Is it saying that when the wait() method is called it is actually releasing the lock before the wait() returns (i.e. this happens without caller knowing)? Or is it just alluding to wait(timeout) releasing the lock when the timeout elapses? If it is the former why would it release the lock before notify()? This seems like a vague and poorly explained statement.
For a thread to call wait() or notify(), the thread has to be the owner of the lock for that object.
Otherwise, a runtime error occur and the rest of code is not executed.
When the thread waits, it temporarily releases the lock for other threads to use
In more details, call to wait() does the following:
the lock is released
current thread is registered as waiting in the monitor
processor switches to some other thread ready for execution
Then, some thread calls notify() or notifyAll(), which causes one or all threads which are registered as waiting at this monitor to be moved from the wait set to the ready set, waiting for a free processor to execute.
but it will need it again to continue execution.
This means the execution of the thread is continued with executing synchronized statement to regain the lock. After the lock is aquired, then the wait() method returns. wait(timeout) differs in that except for notify() or notifyAll(), it also can return upon the timeout.
In sum, you need to understand how a thread switches between following 4 states:
running on a processor
blocked on synchronized statement
waiting for notification
ready to execute and waiting for a free processor
When a thread calls wait, the thread releases the lock right away and then goes dormant until either the timeout expires, if any, or until it receives a notification, which occurs when another thread acquires the same lock that the waiting thread gave up and calls notify on it (also the scheduler has to pick the waiting thread from among any other waiting threads; calling notify doesn’t notify a given thread, it tells the scheduler to pick a thread from a given lock’s wait set to notify).
Once the thread is woken up by a notify, it has to reacquire the lock in order to leave the wait method, because the thread is still inside of a synchronized method or block. That is what the quote means when it says the thread will need the lock to resume execution.
When a thread calls wait(), it's temporarily releasing the monitor (lock) of the object until it receives a notification from another thread. This way, a thread can willingly give control (that it has, in the first place) of the object's monitor to another thread. Take a look at the docs:
The invocation of wait() does not return until another thread has
issued a notification that some special event may have occurred —
though not necessarily the event this thread is waiting for (so always
invoke wait() inside a loop that tests for the condition being
waited for).
...
When wait() is invoked, the thread releases the lock and suspends
execution. At some future time, another thread will acquire the same
lock and invoke Object.notifyAll, informing all threads waiting on
that lock that something important has happened.

What is the state of Java thread during waiting and unable to obtain lock

Java thread can be held by either:
Unable to obtain a lock.
Being held by a wait() method.
What is the difference between the above two scenarios in terms of the Java thread state?
Consider the following simple code:
synchronized(object) {
object.wait();
System.out.println("Completed.");
}
If two threads (say ThreadA and ThreadB) are all being held at the wait() method. When another thread calls notifyAll(), ThreadA will revive from wait and obtain the lock on object and continue, for example. ThreadB will also revive but unable to get the lock on object and be held until ThreadA exits the synchronized block. ThreadB then obtains the lock and continue.
The result will be two "Completed" are printed.
In this example, there must be a time when ThreadB changes from "Being held by wait()" to "Being held because it is unable to get the lock on object".
I want to know how it works internally in Java. Please help.
Difference between being in object.wait() state and waiting for the lock on monitor of object is that thread in the object.wait() state releases all the monitor of object held by it, and it will compete with all the threads in the system to reacquire the monitors again. That makes wait() a special state.
So in your case when A and B (Thread A and Thread B) are in wait state, they don't have the monitor for synchronization object, both of them have been suspended from execution till some other thread calls object.notify() or object.notifyAll(). When the notifyAll() is called JVM wakes up all the threads (in this case A and B) in object.wait() state and they compete to get the monitor of the current synchronized block. If notify() is called then JVM picks up a A or B randomly.
It's to be noted here that JVM is not notifying any specific thread, that's why every waiting thread has to wait in a while(notify_condition_for_me) loop, that validates if the the wait condition has been if not it has to go in the object.wait() state again.
So the correct code should be
synchronized(object) {
while(myResourceArrived) {//like URL data, JDBC data or something
object.wait();
}
System.out.println("Completed.");
}
When A and B are in object.wait() state, they have released all the monitors they previously held for object, so any other thread which is waiting outside the synchronized block will be immediately able to enter the block by acquiring the released monitor of object.
Take a look at Thread.State and more specifically the WAITING and BLOCKED states.
If you are interested in the internal implementation, both can be achieved using LockSupport.park() and LockSupport.unpark(Thread), and that's actually how they are implemented in most places.
P.S. In case you are interested, here are the OpenJDK park() implementations for Windows (line 4946) and Linux (line 5808), and here is the wait()/notify()/notifyAll() implementation (line 1457). They are very well commented, just give it some time if it all looks too complicated on first glance.

Can another thread enter a monitor, while the waiting one is notified?

I am investigating Java concurrency and I've found one interesting question which I cannot answer.
For example, I have three threads: ThreadA, ThreadB and ThreadC. ThreadA enters the monitor, and invokes method wait(). Then ThreadB enters the same monitor, invokes method notify() and continue owning the monitor during some period of time. While ThreadB is owning the monitor, ThreadC tries to acquire the monitor too. My question is whether ThreadC can acquire the monitor earlier then ThreadA when ThreadB release it or not? If it can, why? Which conditions should be followed to reproduce it?
As per the Javadoc on Object.notify():
The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object.
So there exists the possibility that ThreadC owns the monitor before ThreadA. There is no defined order in which any of the threads enter/obtain the monitor, nor is there any priority or fairness mechanism in place for standard synchronization. All it really guarantees is that for a given lock object, only on thread will be in the synchronized block at once.
Given this fact, careful design considerations should go into how threads obtain the lock and for how long. A thread that repeatedly attempts to acquire a lock (acquire and then release but then acquire again) can cause another thread to be locked out indefinitely (called thread starvation).
Using ReentrantLock with a fairness policy can partially overcome this issue at some performance cost (its slightly slower than traditional synchronization).

Use of Notify() in thread communication

The methods wait() and notify() of the Object class are used for inter thread communication. when wait() is called, the object used to synchronize gives up its lock, but when notify is called the lock is not released until the synchronized block completes. So, what is the use of the notify() function? Even if it was not there, the synchronized block would complete and release the lock right?
notify() is responsible for waking the waiting threads ie. taking the thread from wait queue to run queue. That is the waiting thread can be scheduled by the scheduler.
The java.lang.Object.notify() 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.
This method should only be called by a thread that is the owner of this object's monitor. A thread becomes the owner of the object's monitor in one of three ways:
By executing a synchronized instance method of that object.
By executing the body of a synchronized statement that synchronizes
on the object.
For objects of type Class, by executing a synchronized static method
of that class.
The threads which are waiting to take the lock on the object have to be notified that the object they desire to take the lock on is free now, which is what notify() and notifyAll() methods do.

Categories

Resources