Suppose in multi-threaded environment there are 5 threads t1,t2,t3,t4,t5.... Thread t1,t2,t3,t4 calls the wait() method (inside synchronized block) and only Thread t5 calls notify() method then which thread going to get priority to again acquire the lock in critical section.
The choice is arbitrary and any one of the 4 threads may be woken up. The intrinsic lock in java is not fair which will cause some of the waiting threads to wait longer than others even though they attempted to gain the lock first. A ReentrantLock can be used to grant access to the longest waiting thread if this matters for your program.
Related
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.
This question is full theoretical, I'm sorry but I cannot avoid this time.
I'm learning about ReentrantLock and read this:
Note however, that fairness of locks does not guarantee fairness of thread scheduling.
What does this mean? How can I imagine this?
Let's suppose that the lock is not held by anyone right now:
thread scheduler wakes up t1 thread (who is not the longest waiting thread)
t1 tries to acquire the lock
lock rejects t1 because t1 is not the longest waiting thread
t1 goes to sleep
thread scheduler wakes up a thread
Does Java work this way? In a very unsuccesful case this would mean lots of context switching (that leads to poor throughput, that is written down in the documentation).
What does this mean?
The OS will schedule the thread to run whenever it likes.
How can I imagine this?
The OS has little idea what the JVM would like to run next.
Does Java work this way?
Yes, Java doesn't control the OS scheduler.
What does this mean?
This means that a thread holding lock may continue holding the lock as long as it wants and can reacquire the same lock many time in succession and the longest waiting thread will keep waiting until current thread releases the lock.
So, fairness guarantee comes to play only when lock is free and java thread scheduler has to decide which thread the lock should be given to. And it is given to longest waiting thread(in case of synchronized, it's random).
It also means that the thread holding the lock is not being scheduled frequently and other threads are given more CPU time, so this thread is not able to complete and thus not releasing the lock.
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).
sleep() maintains the lock but wait() does not,
my thinking on wait is that it releases the lock as to give other threads a chance to acquire the monitor on that thread while he is waiting.
but having doubt with sleep() why thread maintains the lock while sleeping as it always comes to the runnable state after sleeping
why thread maintains the lock while sleeping as it always comes to the runnable state after sleeping
Consider the below scenario:-
private Object objLock = new Object();
public void myMethod() {
....
synchronized(objLock) {
Thread.sleep(1000); // make the current running thread sleep for 1 second only.
... // Code here which needs to be executed immediately after 1 second sleep time
}
....
}
If at all JVM relesed lock when sleep was called in the above code then when it comes back to runnable state (resumption of execution will depend on scheduling and the availability of processors on which to execute the thread as per JLS Sleep ) your program may not resume at all if another thread by chance took a lock which would make the program behaviour inconsistent. This could be one of the reasons why it doesnot release any locks.
Thread.sleep doesn't have anything to do with locking.
Object.wait needs to be called when holding a lock because the test for the condition to stop waiting needs to be done while holding the lock, in order to have a consistent view of the condition. But usually a thread isn't holding a lock while sleeping.
Sleeping while holding a lock would seem like really bad behavior. But if you need multiple locks, where you acquire one, and have to back off before retrying getting the other, then sleeping while holding a lock might make sense. If calling sleep released locks, this kind of back-off tactic would not work.
Having Thread.sleep be oblivious to locks makes the API simpler and gives the programmer more options (by not totally ruling out its use by a thread that needs to hold onto a lock).
Q: What does Thread.sleep(n) do?
A: NOTHING. Absolutely nothing at all.
Q: How long does it take?
A: At least n milliseconds if the thread is not interrupted.
You don't need to know much else about Thread.sleep().
Say I have three threads, thread 1, thread 2, and thread 3 all sharing the same lock. Thread 2 acquires the lock, does some work and then blocks via a call to the await method. Thread 1 then acquires the lock, does some work, and during the middle of it, thread 3 tries to acquire the lock but is blocked since thread 1 is holding it. Thread 1 finishes working and, before terminating, signals thread 2 that it can reacquire the lock. So what happens then? Will thread 2 or thread 3 acquire the lock next?
Thank you so much for your time and help in advance.
If no priority is given, whoever comes first will acquire the lock.
While mutual exclusion may provide safety property, it does not ensure liveness property. There can be cases where a thread keeps coming first to acquire the lock, resulting in starvation (other threads wait forever because someone keeps occupying).
Google with the keywords highlighted will help you understand more. I found these slides really comprehensive http://www.cs.cornell.edu/Courses/cs414/2004su/slides/05_schedule.pdf
If you're using a ReentrantLock (or any of its subclasses), you can pass a "fairness" flag to the constructor. If set to true, this will ensure that control of the lock passes to the longest-waiting thread, in this case your Thread 1.
Lock lock = new ReentrantLock(true);