When calling notify() in a thread in which there are multiple instances waiting, how does Java(or JVM) choose which thread to wake up?
Sources you can use for an answer:
Java Language Specification chapter 17.2.2 Notification:
There is no guarantee about which thread in the wait set is selected.
Javadoc on Object.notify() reads:
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.
notify method wakes up only one thread waiting on the object and that thread starts execution. So if there are multiple threads waiting for an object, this method will wake up only one of them. The choice of the thread to wake depends on the OS implementation of thread management.
Related
I am new to OS/multithreading and I'm wondering how wait() and notify() work together. I just saw this: Producer Consumer Solution in Java
And I'm kind of confused. Let's say I called wait() in PC.consume() method. When I reach the line that says notify() in PC.produce(), how does this wait in PC.consume() know that THAT is the one being notified? There could be other places that could be notified so how does it exactly know which to notify?
Thanks!
Wait and notify are called on the same object, the one being used as a lock (in the example that’s the object referenced by the local variable pc). The term used in the javadoc (here is the start of the api doc for the notify method) is “monitor”:
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.
The OS has a thread scheduler that is making the arbitrary decision described in the javadoc, it decides things like when threads get context-switched or who gets notified.
So when a thread in consume waits, it goes dormant. Then eventually some other thread (in the example there are only two threads that acquire the lock on pc) calls notify on the same object the first thread called wait on, the scheduler picks the thread to be notified (has to be the first thread here because nothing else is waiting), and the notified thread wakes up and checks if there is anything to consume so it can know whether to proceed.
Under what conditions can this happen?
As far as I know
Blocked queue is a buffer between threads producing objects and consuming objects.
Wait queue prevents threads from competing for the same lock.
So thread gets a lock, but is unable to be passed onto consumer as it is now busy?
The question makes only sense under the assumption that it actually means “What circumstances can cause a thread to change from the wait state to the blocked state?”
There might be a particular scheduler implementation maintaining these threads in a dedicated queue, having to move threads from one queue to another upon these state changes and influencing the mind set of whoever originally formulated the question, but such a question shouldn’t be loaded with assumed implementation details. As a side note, while a queue of runnable threads would make sense, I can’t imagine a real reason to put blocked or waiting threads into a (global) queue.
If this is the original intention of the question, it should not be confused with Java classes implementing queues and having similar sounding names.
A thread is in the blocked state if it tries to enter a synchronized method or code fragment while another thread owns the object monitor. From there, the thread will turn to the runnable state if the owner releases the monitor and the blocked thread succeeds in acquiring the monitor
A thread is in the waiting state if performs an explicit action that can only proceed, if another thread performs an associated action, i.e. if the thread calls wait on an object, it can only proceed when another thread calls notify on the same object. If the thread calls LockSupport.park(), another thread has to call LockSupport.unpark() with that thread as argument. When it calls join on another thread, that thread must end its execution to end the wait. The waiting state may also end due to interruption or spuriuos wakeups.
As a special case, Java considers threads to be in the timed_waiting state, if they called the methods mentioned above with a timeout or when it executes Thread.sleep. This state only differs from the waiting state in that the state might also end due to elapsed time.
When a thread calls wait on an object, it must own the object’s monitor, i.e. be inside a synchronized method or code block. The monitor is released upon this call and reacquired when returning. When it can’t be reacquired immediately, the thread will go from the waiting or timed_waiting state to the blocked state.
Trying to understand wait() and notify(). I know when thread A went to wait() it will be waked up by notify() from other thread.
But what will happens if threads A,B,C went to wait() in represented order? Who will be waked up by notify()? According to my experiments A thread will be waked up at first. I'm right?
Does it means that system knows in which order threads went to wait() ?
From the documentation for notify(), emphasis mine:
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.
Some other APIs, such as Semaphore, have a concept of "fairness", where you can ensure that threads do proceed in the order in which they blocked.
Section 17.2.2 Notification of Java Language Specification:
There is no guarantee about which thread in the wait set is selected.
So, observed behavior is not guaranteed and should not be relied upon.
No, the VM does not know in which order the threads were put in Waiting state.
When you call notify(), one of them will be back to Alive/Runnable state and there is no way to know which one the VM will choose.
Sometimes they can run in the order they were put in Waiting state, but the specification does not guarantee that. So in a different VMs you can have a completely different results or even in the same VM, if you run the code multiple times.
No, there is no guarantee about the order. The javadoc of the notify method is pretty clear on this:
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.
There's no such an order. Either thread has an equal opportunity to get into runnable state. Actually JVM/OS can see them only as a set of waiting threads, they don't know any order.
In terms of your experiment, to get into a fair conclusion, actually you have to perform it for a huge number of times.
In threads, you can expect an order (FIFO), only if you are using something like a strong Semaphore. Then these threads are put into a waiting queue and fist comer would be first served.
I understand that Thread.currentThread().yield() is a notification to thread scheduler that it may assign cpu cycle to some other thread of same priority if any such is present.
My question is: If current thread has got lock on some object and calls yield(), will it loses that lock right away? And when thread scheduler finds out there is no such thread to assign cpu cycle, then the thread which has called yield() will again be in fight to get lock on the object which it has lost earlier??
I couldn't find it in javadoc and forums [http://www.coderanch.com/t/226223/java-programmer-SCJP/certification/does-sleep-yield-release-lock] have 50-50 answers.
I think yield() (lets say thread1) should release lock because if some thread (lets say thread2) of same priority wants to operate on same object, then it can have chance when thread scheduler eventually assign cup to thread2.
No. Thread.yield() is not like Object.wait(). It just gives up control to allow a thread switch. It will have no effect on the concurrency of your program.
There is no guarantee which thread the scheduler will run after a yield.
In Java Language specification
17.3 Sleep and Yield
It is important to note that neither Thread.sleep nor Thread.yield have any synchronization semantics. In particular, the compiler does not have to flush writes cached in registers out to shared memory before a call to Thread.sleep or Thread.yield, nor does the compiler have to reload values cached in registers after a call to Thread.sleep or Thread.yield.
My comment:
In java's early days, when it did not really supported parallel executions, but only concurrent (green threads), yield() was suspending the current thread, and the jvm was picking up another thread to resume. Now-days, yield does not have much meaning as usually the tread scheduling is on OS level.
So, yield is just a hint to the JVM that current thread wants to take a rest and nothing else, it is up to the thread scheduler to decide what to do. yield does not have any synchronization semantic. If thread holds lock, it will continue to hold it.
Only wait methods of the Object class release the intrinsic lock of the current instance (the thread may have other locks acquired, they don't get released). Yield, sleep, join do not bother about locks. However, join is a little more special, you are guaranteed to see all the changes made by the thread you're waiting for to finish.
I've read many docs about thread states, some of them tells that there is two different states: blocked (before synchronized) and wait (if calls wait), some others are telling that there is only one state: wait. Moreover, some docs telling that you should call notify() for every wait() and if you don't then threads waiting() will never be eligible for execution even if monitor is unlocked.
From you last sentence I see you don't fully understand the difference between synchronized and wait()/notify().
Basically, monitor has lock and condition. It's almost orthogonal concepts.
When thread enters a synchronized block, it acquires a lock. When thread leaves that block, it releases a lock. Only one thread can have a lock on a particular monitor.
When thread having a lock calls wait(), it releases a lock and starts waiting on its condition. When thread having a lock calls notify(), one of the threads (all threads in the case of notifyAll()) waiting on the condition becomes eligible for execution (and starts waiting to acquire a lock, since notifying thread still has it).
So, waiting to acquire a lock (Thread.State.BLOCKED) and waiting on the monitor's condition (Thread.State.WAITING) are different and independent states.
This behaviour becames more clear if you look at Lock class - it implements the same synchronization primitives as synchronized block (with some extensions), but provides clear distinction between locks and conditions.
There are two different states BLOCKED and WAITING.
The part about waiting forever if no one notifies (or interrupts) you is true.
Standard doc is here
When a thread calls Object.wait
method, it releases this acquired
monitor and is put into WAITING (or
TIMED_WAITING if we call the timeout
versions of the wait method) state.
Now when the thread is notified either
by notify() or by notifyAll() call on
the same object then the waiting state
of the thread ends and the thread
starts attempting to regain all the
monitors which it had acquired at the
time of wait call. At one time there
may be several threads trying to
regain (or maybe gain for the first
time) their monitors. If more than one
threads attempt to acquire the monitor
of a particular object then only one
thread (selected by the JVM scheduler)
is granted the monitor and all other
threads are put into BLOCKED state.
In Java's perspective (Thread.State), there are two different states: BLOCKED and WAITING . When a thread synchronizes on a Object, it is in BLOCKED state. After a thread executes wait, it is in WAITING state.
On Linux platform, Java thread is OS native thread. The OS thread state for both BLOCKED and WAITING states is Interruptible sleep. When being checked with ps, the state for both BLOCKED and WAITING threads is "Sl+".