I was reading about wait and notify in Java.
I will explain with a small example:
#Override
public void run() {
synchronized (msg) {
try{
msg.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(name+" processed: "+msg.getMsg());
}
}
Here it says that when we do synchronized (msg). The current thread T1 will take a lock on the msg Object.
So the lock can be released via 2 ways :
After the synchronized block is completed
when the wait() is called by T1 ??
And if some another thread calls notify() and woke up the the thread T1, T1 will again gain access to lock on msg object?
Yes, T1 will release the lock when wait, and it has to re-aquire the lock after getting notified. See the details in java language specification.
And, the wait method should be called in a while loop.
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
Lock is released after invoking wait().
And if some another thread calls notify() and woke up the the thread T1, T1 will again gain access to lock on msg object?
It won't gain access to lock automatically. It has to compete with other Threads.
On notify() ( from javadocs) :
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. A thread waits on an object's monitor by calling one of the wait methods.
The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object. 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.
Related
I get confused on the synchronized method. Look at this code below:
public void waitOne() throws InterruptedException
{
synchronized (monitor)
{
while (!signaled)
{
monitor.wait();
}
}
}
public void set()
{
synchronized (monitor)
{
signaled = true;
monitor.notifyAll();
}
}
Now, from what I understand, synchronized means only 1 thread can access the code inside. If waitOne() is called by main thread and set() is called by child thread, then (from what I understand) it will create deadlock.
This is because main thread never exit synchronized (monitor) because of while (!signaled) { monitor.wait(); } and therefore calling set() from child thread will never able to get into synchronized (monitor)?
Am I right? Or did I miss something? The full code is in here: What is java's equivalent of ManualResetEvent?
Thanks
When you call wait on an object that you use to synchronize on, it will release the monitor, allowing​ another thread to obtain it. This code will not deadlock.
Have a look at documentation of wait() method.
Causes the 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. 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.
The key point is the thread releases ownership of monitor and hence you won't get deadlock. Child thread can set the value of signaled and can notify main thread.
I am new to Java and came across this link: http://tutorials.jenkov.com/java-concurrency/slipped-conditions.html while understanding multithreading in java.
In this tutorial the code below is called out as a good practice to avoid slipped conditions:
public class Lock {
private boolean isLocked = true;
public void lock(){
synchronized(this){
while(isLocked){
try{
this.wait();
} catch(InterruptedException e){
//do nothing, keep waiting
}
}
isLocked = true;
}
}
public synchronized void unlock(){
isLocked = false;
this.notify();
}
}
My doubt is that in case two threads A & B call lock() at the same time and isLocked is true i.e. lock has been taken by some other thread C. Now:
--1 A enters synchronized block first (as only one can obtain lock on monitor-object this and enter a synchronized block)
--2 A calls this.wait() and so releases lock on monitor-object this (wait() call releases the lock on monitor-object http://tutorials.jenkov.com/java-concurrency/thread-signaling.html#wait-notify) but remains inside synchronized block
--3 Now B enters synchronized block (as A has released lock on monitor-object this)
--4 B calls this.wait() and so releases lock on monitor-object this (wait() call releases the lock on monitor-object)
--5 at this moment thread C calls unlock() i.e. sets isLocked to false and calls this.notify()
--6 Now one of A and B come out wait(), then come out of while loop and set isLocked to true
--7 and the cycle continues
So in --3, both A and B are inside a synchronized block at the same time, is it not in violation of the basic multithreading principle that only one thread is allowed inside a synchronized block at a time?
Please clarify my doubt.
A thread can only return from the wait() method if it reacquires the lock on the object it's waiting on. In your scenario, A and B would compete to get the lock, only one of them would get it and the other one would keep waiting until the lock is released again.
From the javadoc (emphasis mine):
The current thread must own this object's monitor. 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.
The following code did not block when the spawned thread tried to obtain the lock on itself.
Does the spawned thread inherits locks from the spawning thread?
Here's the code:
public class A {
public void methodA() {
public class SpawnedThread extends Thread {
public void run() {
synchronized(this) {
...
}
};
SpawnedThread spawnedThread= new SpawnedThread ();
synchronized(spawnedThread) {
spawnedThread.start();
spawnedThread.join();
};
...
}
}
Threads don't inherit locks from other threads, something else is going on here.
In your example the thread that is running methodA has to take the lock on the spawnedThread before it can enter the synchronized block.
Then when the spawnedThread runs it must acquire the lock on itself in order to enter the synchronized block in the run method.
So the methodA thread has the lock and spawnedThread is trying to get the same lock. But it won't deadlock because Thread.join performs waits where it gives up the lock, see the api documentation for Thread.join:
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.
The version of Thread.join without a timeout value takes the lock on the thread it's joining, gives it up, and goes dormant. It doesn't wake up until one of the following happens:
1) the thread being joined finishes (sending a notification that wakes the waiting thread)
2) the joining thread is interrupted (meaning something calls interrupt on it, which doesn't happen in this example)
3) the joining thread wakes up on its own (a "spurious wakeup", which is rare, a result of a race condition)
I'm not clear on how you would change the locks to get a deadlock here as you described in your comment, if you want that answered please add that version of the code to your question.
Does the spawned thread inherits locks from the spawning thread?
No, nor do you hold any lock in the spawning thread for the spawned thread to inherit.
You can attempt to do this with a Lock but it will throw an IllegalMonitorStateException if you try.
"synchronized(spawnedThread) { spawnedThread.start(); };" after instantiating spawnedThread.
As soon as you exit this block, the spwaned thread can obtain the lock. Move the join() inside the synchronized block if you want to see a deadlock.
What is the difference between thread state WAIT and thread state BLOCKED?
The Thread.State documentation:
Blocked
A thread that is blocked waiting for a monitor lock is in this state.
Waiting
A thread that is waiting indefinitely for another thread to perform a particular action is in this state
does not explain the difference to me.
A thread goes to wait state once it calls wait() on an Object. This is called Waiting State. Once a thread reaches waiting state, it will need to wait till some other thread calls notify() or notifyAll() on the object.
Once this thread is notified, it will not be runnable. It might be that other threads are also notified (using notifyAll()) or the first thread has not finished his work, so it is still blocked till it gets its chance. This is called Blocked State. A Blocked state will occur whenever a thread tries to acquire lock on object and some other thread is already holding the lock.
Once other threads have left and its this thread chance, it moves to Runnable state after that it is eligible pick up work based on JVM threading mechanism and moves to run state.
The difference is relatively simple.
In the BLOCKED state, a thread is about to enter a synchronized block, but there is another thread currently running inside a synchronized block on the same object. The first thread must then wait for the second thread to exit its block.
In the WAITING state, a thread is waiting for a signal from another thread. This happens typically by calling Object.wait(), or Thread.join(). The thread will then remain in this state until another thread calls Object.notify(), or dies.
The important difference between the blocked and wait states is the impact on the scheduler. A thread in a blocked state is contending for a lock; that thread still counts as something the scheduler needs to service, possibly getting factored into the scheduler's decisions about how much time to give running threads (so that it can give the threads blocking on the lock a chance).
Once a thread is in the wait state the stress it puts on the system is minimized, and the scheduler doesn't have to worry about it. It goes dormant until it receives a notification. Except for the fact that it keeps an OS thread occupied it is entirely out of play.
This is why using notifyAll is less than ideal, it causes a bunch of threads that were previously happily dormant putting no load on the system to get woken up, where most of them will block until they can acquire the lock, find the condition they are waiting for is not true, and go back to waiting. It would be preferable to notify only those threads that have a chance of making progress.
(Using ReentrantLock instead of intrinsic locks allows you to have multiple conditions for one lock, so that you can make sure the notified thread is one that's waiting on a particular condition, avoiding the lost-notification bug in the case of a thread getting notified for something it can't act on.)
Simplified perspective for interpreting thread dumps:
WAIT - I'm waiting to be given some work, so I'm idle right now.
BLOCKED - I'm busy trying to get work done but another thread is standing in my way, so I'm idle right now.
RUNNABLE...(Native Method) - I called out to RUN some native code (which hasn't finished yet) so as far as the JVM is concerned, you're RUNNABLE and it can't give any further information. A common example would be a native socket listener method coded in C which is actually waiting for any traffic to arrive, so I'm idle right now. In that situation, this is can be seen as a special kind of WAIT as we're not actually RUNNING (no CPU burn) at all but you'd have to use an OS thread dump rather than a Java thread dump to see it.
Blocked- Your thread is in runnable state of thread life cycle and trying to obtain object lock.
Wait- Your thread is in waiting state of thread life cycle and waiting for notify signal to come in runnable state of thread.
see this example:
demonstration of thread states.
/*NEW- thread object created, but not started.
RUNNABLE- thread is executing.
BLOCKED- waiting for monitor after calling wait() method.
WAITING- when wait() if called & waiting for notify() to be called.
Also when join() is called.
TIMED_WAITING- when below methods are called:
Thread.sleep
Object.wait with timeout
Thread.join with timeout
TERMINATED- thread returned from run() method.*/
public class ThreadBlockingState{
public static void main(String[] args) throws InterruptedException {
Object obj= new Object();
Object obj2 = new Object();
Thread3 t3 = new Thread3(obj,obj2);
Thread.sleep(1000);
System.out.println("nm:"+t3.getName()+",state:"+t3.getState().toString()+
",when Wait() is called & waiting for notify() to be called.");
Thread4 t4 = new Thread4(obj,obj2);
Thread.sleep(3000);
System.out.println("nm:"+t3.getName()+",state:"+t3.getState().toString()+",After calling Wait() & waiting for monitor of obj2.");
System.out.println("nm:"+t4.getName()+",state:"+t4.getState().toString()+",when sleep() is called.");
}
}
class Thread3 extends Thread{
Object obj,obj2;
int cnt;
Thread3(Object obj,Object obj2){
this.obj = obj;
this.obj2 = obj2;
this.start();
}
#Override
public void run() {
super.run();
synchronized (obj) {
try {
System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",Before Wait().");
obj.wait();
System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",After Wait().");
synchronized (obj2) {
cnt++;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Thread4 extends Thread{
Object obj,obj2;
Thread4(Object obj,Object obj2){
this.obj = obj;
this.obj2 = obj2;
this.start();
}
#Override
public void run() {
super.run();
synchronized (obj) {
System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",Before notify().");
obj.notify();
System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",After notify().");
}
synchronized (obj2) {
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
I'm very confusing about these two descriptions:
"The wait method blocks the calling thread and gives up the monitor lock"
"The notify method unblocks one waiting thread but does not give up the monitor lock"
Here is my questions:
I know each object in Java has a lock, but what is the "monitor lock" means? is it the same as the oject's lock?
Why notify method needs to give up the monitor lock?
If I try to make a object waiting with the following code:
class simpleTask extends Thread
{
int waitingTime;
public simpleTask(int waitingTime)
{
this.waitingTime = waitingTime;
}
public void run()
{
synchronized(this) // this is a reference of current object
{
try {
this.wait(waitingTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Like the first description above, is that means the the current object is blocked by synchronized keyword, and then wait method releases the lock?
I know each object in Java has a lock, but what is the "monitor lock" means? is it the same as the object's lock?
Yes, they are the same thing. They are also occasionally called the object's "mutex" and the object's "primitive lock". (But when someone talks about Lock, they are talking about this Java interface ... which is a different locking mechanism.)
Why notify method needs to give up the monitor lock?
The notify method doesn't give up the lock. It is your code's responsibility to give up the lock (i.e. leave the synchronized block or return from the synchronized method) after the notify call returns.
Why is that necessary? Because any other thread that is currently waiting on that lock (in a wait(...) call) has to reacquire that lock before the wait call can complete.
Why did they design notify / wait like this? So that they can be used to implement condition variables.
Like the first description above, is that means the the current object is blocked by synchronized keyword, and then wait method releases the lock?
That is correct. When a thread calls someObject.wait() its lock on someObject is released ... and then reacquired (by the same thread) before the wait() call returns. Of course, in the meantime the lock someObject may have been acquired and released multiple times by other threads. The point is that when wait returns, the thread that called wait will have the lock.
Yes, the monitor lock is the same as the object's lock. If you do synchronized (object), that's the lock.
In your example, the current object will give up the lock while waiting, the wait() call gives up the lock. In another thread, notify() is called to wake the object up, and when the wait() call returns it will hold the lock again.
A monitor is a type of synchronization construct.
The reason that waiting gives up the lock is so that other threads can acquire the lock, such as other threads that might want to wait. Also: It's usual for the thread that's awakening other threads to lock before releasing any threads, to prevent a race condition.
For more about this, you should study condition variables (i.e. condvars).