Suppose I have the following piece of code
public synchronized void method()
{
if(something == null)
{
something = new SomeThing();
}
//do something
}
Now suppose in a multithreaded environment, one thread [Thread 1] enters the method and was preempted just after it executed the new Something(); but before it was able to assign it to something. Then another thread [Thread 2] also tries to call the method. What exactly happens now? What happens to the lock that Thread 1 had acquired? Will Thread 1's steps be rolled back?
Thread1 did not give up the lock, so it still owns it. When Thread2 prepares to take the lock it will discover that it has to wait and enter a BLOCKED state. The next time the OS schedules Thread1 it will finish execution and release the lock. This allows Thread2 to be schedulable again.
Thread 2 will not be able to enter the method until Thread 1 has exited it because it is synchronized.
Eventually the scheduler will get around to continuing with Thread 1, Thread 1 will execute new Something() and exit the method. Then, Thread 2 will be able to enter the function with the new Something() constructed.
The whole idea of the lock is that Thread 1 does not lose it until it is done with it. Thread 1 unlocks when it exits method(), then Thread 2 is able to acquire it.
Related
I have the following code:-
class ThreadB extends Thread {
int total;
#Override public void run() {
synchronized (this){
for(int i=0; i<5; i++){
total+=i;
}
}
}
}
public class Solution {
public static void main(String[] args) throws InterruptedException {
ThreadB b = new ThreadB();
b.start();
synchronized (b){
b.wait();
}
System.out.println(b.total);
}
}
Whenever I run this I get my output as 10.
If I comment the wait line I get the output as 0 always.
I am confused as to why do I get my answer as 10 always.
There are 2 threads , ThreadB and main thread so when I execute the wait method then ThreadB should be waiting as per definition and values should not get added and hence 0 should be printed by main thread then?
Every object has an intrinsic lock that threads can acquire using synchronized. A thread calls wait when there isn't anything it can do until something changes (for instance,
it might be trying to insert into a bounded queue that is currently full), it calls wait on the object whose lock it acquired with synchronized. When the main thread calls b.wait(), it means the main thread is the one that is going dormant.
When the code has wait commented out the ThreadB thread is still in the process of starting and the main thread can take the lock, then release the lock and print total before ThreadB can acquire the lock, at which time total is still 0. Technically there is a race and it's not guaranteed which thread goes first but the main thread has a good head start.
When the code uses wait then the main thread acquires the lock on ThreadB (again getting there ahead of ThreadB), then waits until it receives a notify. It happens that when a thread terminates it causes the scheduler to notify any threads in its waitset, so when threadB finishes it causes the main thread to wake up and proceed from there. Since ThreadB is done total is 10 by the time the main thread gets around to printing it.
If somehow the main thread did not get the lock before ThreadB, then (since ThreadB holds onto the lock for the whole time it is running) it couldn't acquire the lock until after ThreadB was finished. That would mean it wasn't in the waitset at the time the dying thread sent its notification, but would wait later, and there wouldn't be any notification to wake it up and it would hang.
This kind of problem - races that result in lost notifications and threads hanging - can happen when wait/notify is misused. For the right way to use wait and notify read https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html.
If you specifically want a thread to wait for another thread to finish, Thread has an instance method called join that is used for that, which the main thread would call here like
b.join();
BTW the notify-on-termination behavior is documented in the api doc for java.lang.Thread#join, it says:
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.
Note the warning against synchronizing on Thread objects. It doesn't play nice with JDK code like join that is locking on threads.
I am confused as to why do I get my answer as 10 always. There are 2 threads , ThreadB and main thread so when I execute the wait method then ThreadB should be waiting as per definition and values should not get added and hence 0 should be printed by main thread then?
You are getting a result because of the way Java threads terminate. When a Thread finishes, the Thread object itself is notified. So your wait() method causes the thread to wait for the termination of the background thread. The join() method is implemented by a call to wait() and you should use join() directly and not wait().
If I comment the wait line I get the output as 0 always.
If you don't have the wait() line then most likely the main thread will finish and get the value of b.total before the b thread is even started. Starting threads take a little bit of time and you need to have b.join() to make sure that you wait for the b thread to finish and to synchronize with any memory changes that the other thread has made, in this case to b.total.
If you put a sleep instead of the wait, you might still see the value of 0 even if the b thread had already set it to 10 because there is nothing that is synchronizing the memory and the b.total value of 0 might be cached. The join() method waits for the thread to finish and synchronized memory so that you can see the results of the thread.
So I Wrote the following code to run one thread to print even numbers and the other to print odd numbers using the same counter variable. However, I am wondering what internal mechanism causes notify() to trigger only after wait(), even if notify() is called before wait() and there is an operation in between.
As in T1 issues notify() but goes in wait() state only after iterating 10000 times. Shouldn't t2 already try and get the lock as soon as notify is triggered or does notify() by design wait for wait() to be invoked?
PS: I see that irrespective of where I put the notify() call, it is always invoked after wait() as long as I write it before the wait() call.
import java.io.IOException;
public class PrintThread implements Runnable {
int i = 0;
private final Object lock = new Object();
public void run() {
synchronized (lock) {
while (i <= 10) {
System.out.println(Thread.currentThread().getName() + " i is " + i);
i++;
lock.notify();
//Just to add some delay
for(int i=0;i<10000;i++){}
try {
lock.wait();
} catch (InterruptedException e) {
System.out.println("Error");
}
}
System.out.println(Thread.currentThread().getName() + " Exiting!");
}
}}
And the Driver Program
public class PrintThreadDriver {
public static void main(String args[]) throws InterruptedException {
PrintThread obj1 = new PrintThread();
Thread t1 = new Thread(obj1);
Thread t2 = new Thread(obj1);
t1.start();
t2.start();
}}
Output:
Thread-0 i is 0
Thread-1 i is 1
Thread-0 i is 2
Thread-1 i is 3
Thread-0 i is 4
Thread-1 i is 5
Thread-0 i is 6
Thread-1 i is 7
Thread-0 i is 8
Thread-1 i is 9
Thread-0 i is 10
Thread-1 Exiting!
Also I see that one of the thread continues to be in wait state. Any Ideas as to how I can cause that to terminate once the counter reaches 10?
For lock object you have wait set and blocked set.
Here what is happening in your program:
The First thread is started, the monitor is locked (lock is captured)
The Second thread is started, but since the monitor is locked the second thread goes to Blocked Set.
The first thread prints "Thread-0 i is 0", do operations and calls notify from lock. Nothing is happening because notify removes a random thread from wait set. For now we have an empty wait set. The second thread is still in blocked set.
The first thread waits a little in a spin-lock, calls wait and goes to wait set. The monitor is unlocked, the Second thread takes the monitor and starts working, The monitor is taken by the second thread.
The second thread prints "Thread-1 i is 1" and calls notify. The first thread is removed from wait set and goes to blocked set since the monitor is still tacked by the second thread. The second thread calls wait and goes to wait set. The monitor is unlocked.
The first thread takes the monitor and continue working from the line when it called lock.wait().
The first thread continue the loop and prints "Thread-0 i is 2" and then calls notify. The second thread is removed from wait set and placed to blocked set. The first thread calls wait and goes to wait set. The monitor is unlocked.
The second thread takes the monitor and continue working from the line when it called lock.wait().
The second thread continue the loop and prints "Thread-1 i is 3" and then calls notify. The first thread is removed from wait set and placed to blocked set. The second thread calls wait and goes to wait set. The monitor is unlocked.
Items 6-9 are repeated while i < 10.
Now, lets describe the last iteration:
i=10. The second thread is in wait set. The monitor is blocked by the first thread. The first thread continue the loop and prints "Thread-0 i is 10". Then the first thread calls notify, the second thread is removed from wait set and goes to blocked set. The first Thread calls wait and goes to wait set. The monitor is unlocked.
The second thread takes the monitor and continue working from the line when it called lock.wait().
The second thread exits the loop because i==11, prints "Thread-1 Exiting!" and unlocks the monitor. The Second thread is finished.
The monitor is unlocked, but the first thread is still in wait set and it will be there forever because nobody will call notify! (Except spurious wakeup case)
Since the thread first thread is not demon the program will not finished.
For you case just duplicate lock.notify(); right after the loop to remove the first thread from wait set and to let him to finish.
All needed proofs and confirmations of the behavior described below you can find here:https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html
PS: Notify will never invoke the other waiting thread immediately. It will just remove a thread from Wait Set and then this thread will be invoked by the Operating System! And if the thread will try to enter to the locked monitor (synchronized block) that is already taken by another thread, it will be placed to the blocked set until it can obtain the lock on that monitor.
In java If a thread calls notify() before wait(), how does this not cause the second thread to enter the block before the first goes to wait state?
Because the first thread still holds the lock until it calls wait() or exits the synchronized block. From the Javadoc:
The awakened thread wil be unable to proceed until the current
thread relinquishes the lock on this object.
Wait means that the current thread which has the lock, will give out the lock to another thread in the thread pool, the next thread that acquire the lock(decided by thread scheduler) will complete the task and then notify back to the previous thread with notify(). After notify() then the waiting thread which gave the lock will resume its task.
public void add(int num)
{
synchronized(myObject){
// line 1
//line 2
while(!condition)
{
myObject.wait();
//line 3
}
//line 4
//line 5
//line 6
}
}
When a thread T (waiting for lock on myObject) is notified,
where does T start its execution, at line line 1 or line 3? Thanks.
It is at line 3, thread execution is linear, it
cannot go back, or jump to somewhere just like that.
The notified thread needs to re-acquire the lock, but that re-acquisition happens within the call to wait and the thread has the lock once it returns from the wait method, then it starts executing at line 3. Peter's answer is correct (+1).
The javadoc for wait supports this, it says:
The thread T is then removed from the wait set for this object and re-enabled for thread scheduling. It then competes in the usual manner with other threads for the right to synchronize on the object; once it has gained control of the object, all its synchronization claims on the object are restored to the status quo ante - that is, to the situation as of the time that the wait method was invoked. Thread T then returns from the invocation of the wait method. Thus, on return from the wait method, the synchronization state of the object and of thread T is exactly as it was when the wait method was invoked.
You can test this. If the thread had to start over at the top of the block then you could get by with an if test to check the condition, because once the thread was notified it would still have to make it past the condition test. If the thread picks up where it left off you need the while loop, because the thread needs to check that the condition that made it have to wait is not still true. If you replace the while loop with an if statement and run a multi-threaded test (for instance, you could create a queue, a homegrown one where you can tamper with its put and take methods, with multiple producers and consumers where the consumers are waiting for the queue to be non-empty) then you should be able to see cases where the thread waits, then proceeds even though the condition shouldn't let it (resulting in trying to take something from an empty queue).
It is an advocated paradigm that wait() should be invoked inside a while loop inside a synchronized block.
My question is how does the waiting() thread get the lock back ?
// Thread 1
synchronized (mon) {
while (!condition)
mon.wait();
// Do something
}
//Thread 2
synchronized (mon) {//set condition appropriately
mon.notify();
}
Consider the thread 1 runs first and starts waiting for the condition. It releases the lock and the thread 2 obtains the lock sets the condition and notifies thread 1. Now thread 1 gets the lock, checks the condition and starts executing "do something".
My question is when Thread 1 is notified it starts execution from the while condition, the line of code which had Synchronized(mon) is never executed again then how does thread 1 acquire the lock ? What are the internal dynamics that give the lock back to Thread 1 ?
When Thread1 is notified the thread has to acquire the lock before it can exit the wait method, see the java doc for Object#wait:
The thread T is then removed from the wait set for this
object and re-enabled for thread scheduling. It then competes in the
usual manner with other threads for the right to synchronize on the
object; once it has gained control of the object, all its
synchronization claims on the object are restored to the status quo
ante - that is, to the situation as of the time that the wait
method was invoked. Thread T then returns from the
invocation of the wait method. Thus, on return from the
wait method, the synchronization state of the object and of thread
T is exactly as it was when the wait method was
invoked.
synchronized(mon) is not an expression that has to be executed.
It's a syntax element in the source code that tells the compiler (and then the runtime) that the wrapped section of the code must only be executed after the lock associated with mon has been acquired by the current thread, even if you don't "come from" the line of code before the synchronized block.
wait() releases the lock, and must reacquire it before returning.
After Thread 1 is notified, it got the lock immediately and start to run //Do something.
When Thread 1 wait, it just release the lock temporarily, and when the thread is notified, it can get the lock again and needn't run synchronized(...).
// Thread 1
synchronized (mon) {
Systemout.println("I am invoked!");
while (!condition)
mon.wait();
// Do something
}
//Thread 2
synchronized (mon) {//set condition appropriately
mon.notify();
}
In the original scenario:
Consider the thread 1 runs first and starts waiting for the condition. It releases the lock and the thread 2 obtains the lock sets the condition and notifies thread 1. Now thread 1 gets the lock, checks the condition and starts executing "do something".
If my understand the following correctly:
The thread T is then removed from the wait set for this object and re-enabled for thread scheduling. It then competes in the usual manner with other threads for the right to synchronize on the object; once it has gained control of the object, all its synchronization claims on the object are restored to the status quo ante - that is, to the situation as of the time that the wait method was invoked. Thread T then returns from the invocation of the wait method. Thus, on return from the wait method, the synchronization state of the object and of thread T is exactly as it was when the wait method was invoked.
the line
Systemout.println("I am invoked!");
will not be executed, as "Thus, on return from the wait method, the synchronization state of the object and of thread T is exactly as it was when the wait method was invoked."
Am I right?
i am doing a sleeping barber prob. So, first i create 10 customer threads with 2 sec "sleep" between each other. now, the first client gets hair cut, means sleeping 5 sec.. we have waiting room for following threads where we have place for only 3 threads.
if a customer thread is getting hair cut, and 3 following threads are in queue, other customer threads created after that must stop unless there is an available position in 3 sit waiting room.
when 1st customer gets cut, second customers cut starts,, so 2 threads are in queue, only in this case one more thread can join the waiting.
to do all these task, can someone tell me in short, where to use sleep, interrupt and join. especially how to make threads wait for others to finish, and how to detect how many threads are currently waiting/sleeping?
You can use additiv semaphores with 3 places for the waiting room and one binary semaphore for the barber.
Semaphore waitingRoom = new Semaphore(3);
Semaphore barber= new Semaphore(1);
The method cut shoud be like this:
waitingRoom.acquire();
barber.acquire();
waitingRoom.release()
Thread.sleep(300)
barber.release()
You use .join() only if you waiting for a thread to continue your programm. You don't need to interrupt this thread, it must just finish his run().
.interrupt() will hold on the thread.
sleep() method delays the execution of a thread by specified period of time. While sleeping, the thread does not release its lock. It still holds it.
If a thread calls join method on another thread, then it means that the thread will become runnable only after another has completed running. e.g.
public static void main(String[] args){
Thread thread1 = new Thread();
thread1.join();
}
Above code means that the main thread will become runnable after the thread1 has completed running.
If you use overloaded version of join method.
thread1.join(100)
This will mean that wait for 100 milliseconds for the thread1 to complete, but if that doesn't happen, become runnable anyone. So main thread will become runnable even if thread1 does not complete in 100 milliseconds