I have just written a simple java example to get familiar with the concept of wait and notify methods.
The idea is that when calling notify(), the main thread will print the sum.
MyThread class
public class MyThread extends Thread {
public int times = 0;
#Override
public void run() {
synchronized (this) {
try {
for (int i = 0; i < 10; i++) {
times += 1;
Thread.sleep(500);
if (i == 5) {
this.notify();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Main Class
public class Main {
public static void main(String[] args) {
MyThread t = new MyThread();
synchronized (t) {
t.start();
try {
t.wait();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(t.times);
}
}
}
Expected Results
5 but I got 10 instead.
Well, what I though is that when notify() is called, the main thread will wakeup and execute the System.out.println(t.times) which should give 5. Then the run() will continue till it finishes the for loop which will update the value of times to 10.
Any help is highly appreciated.
Synchronized blocks imply mutual exclusion. At any given moment, only one thread is allowed to hold the lock and execute the code within a synchronized block. This rule spreads over all the blocks guarded by the same lock.
In your case, there're two such blocks that use the same lock, so it's either the main thread or the MyThread that is allowed to execute code in either of these blocks, the other thread must wait. So, you have the following scenario here:
The main thread acquires the lock.
The main thread starts the second thread.
The second thread hits the synchronized block but cannot enter it since the lock is being hold by the main thread.
The main thread calls wait(). This call releases the lock and puts the main thread into the WAITING state.
The second thread now can acquire the lock and enter the synchronized block.
The second thread counts to five and calls notify(). This call doesn't release the lock, it just notifies the main thread that it can progress as soon as it can reacquire the lock.
The main thread awakes but it cannot make progress because it cannot reacquire the lock (it's still being hold by the second thread). Remember, no two threads can be active within a synchronized block guarded by the same lock at once, and now, the second thread is still active, so the main one must continue waiting.
The second thread continues counting, sets times to 10 and eventually leaves the synchronized block, releasing the lock.
The main thread reacquires the lock and can now make progress to the println. But by this time, the times is already 10.
Using join() won't help you either because the result will be the same – the main thread can only make progress when the second one is finished.
If you want your main thread to continue execution as soon as the second thread hits 5, you need to acquire the lock and release it immediately after that event:
public class MyThread extends Thread {
public volatile int times = 0;
#Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
times += 1;
Thread.sleep(500);
if (i == 5) {
synchronized(this) {
this.notify();
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
Don't forget to make times volatile, otherwise JVM won't guarantee that you'll see its actual value in your main thread.
And you should also understand that this approach doesn't guarantee that your main thread prints 5. It might occur that by the time it reaches the println call, the second thread makes one or two or even more iterations and you'll see something greater than 5 (though it's highly unluckily due to the sleep() call on every iteration).
Related
I'm looking at some notify/wait examples and came across this one. I understand a synchronized block essentially defines a critical section, but doesn't this present a race condition? Nothing specifies which synchronized block is entered first.
public class ThreadA {
public static void main(String[] args){
ThreadB b = new ThreadB();
b.start();
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread {
int total;
#Override
public void run(){
synchronized(this){
for(int i=0; i<100 ; i++){
total += i;
}
notify();
}
}
}
Output per website:
Waiting for b to complete...
Total is: 4950
Right, it's not guaranteed which thread will execute first. The thread b could do its notification before the main thread ever starts to wait.
In addition to that, a thread can return from wait without having been notified, so setting a flag and checking it before entering the wait technically isn't good enough. You could rewrite it to something like
public class ThreadA {
public static void main(String[] args) throws InterruptedException {
ThreadB b = new ThreadB();
b.start();
synchronized(b){
while (!b.isDone()) {
System.out.println("Waiting for b to complete...");
b.wait();
}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread {
int total;
private boolean done = false;
#Override
public void run(){
synchronized(this){
for(int i=0; i<100 ; i++){
total += i;
}
done = true;
notify();
}
}
public boolean isDone() {return done;}
}
so that the main thread will wait until b is done with its calculation, regardless who starts first.
By the way, the API documentation recommends you not synchronize on threads. The JDK synchronizes on threads to implement Thread#join. A thread that terminates sends a notifyAll that anything joining on it receives. If you were to call notify or notifyAll from a thread you've acquired the lock on, something joining on it could return early. One side effect of this here is that if you remove the notify the code works the same way.
Yes, it's a race condition. Nothing prevents ThreadB from starting, entering its run method, and synchronizing on itself prior to ThreadA from entering its synchronized block (thus waiting indefinitely). However, it's very unlikely to ever happen, considering the time it takes for a new thread to begin execution.
The easiest, and most recommended way to handle this type of situation is to not write your own implementation, but opt to use a callable/future provided by an Executor.
To fix this particular case without following standards:
Set a boolean 'finished' value set at the end of ThreadB's synchronized block.
If the boolean 'finished' is true after entering the synchronized block, then you should not call wait.
Yes - it is a race as to which thread enters which synchronized block first. For most scenarios of the race, the output and the answer will be the same. For one, however, the program will deadlock:
Main starts calls b.start() and immediately schedules out.
Thread B starts, enters synchronized, calls notify().
Main enters its synchronized block, calls wait()
In this case, main will wait forever since thread b called notify before main blocked on wait().
That said, this is unlikely - but with all threading you should conclude that it will happen and then at the worst possible time.
public class ThreadA {
public static void main(String[] args) {
ThreadB threadB = new ThreadB();
threadB.start();
synchronized (threadB) {
try {
threadB.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("the total is ====>"+threadB.total);
}
}
class ThreadB extends Thread
{
int total;
public void run(){
synchronized (this) {
for(int i =0; i<5;i++)
{
System.out.println("lets add===>"+i);
total+= i;
}
notify(); // line no.31
System.out.println("after notify but within lock");
}
System.out.println("after notify but outside lock");
}
}
output :
lets add===>0
lets add===>1
lets add===>2
lets add===>3
lets add===>4
after notify but within lock
the total is ====>10
after notify but outside lock
My question : shouldn't the control go back to the "Main" thread immediately after line no.31. Ideally shouldn't it print -
"the total is ====>10" immediately after "lets add===>4"?
Why it is that it executes all the statements within the synchronized block irrespective of the notify() statement in line no.31?
the order of last couple of lines will not be same always. it depends on the how the threads are being scheduled and there is no guarantee, based on the code you have. the moment you have executed notify the wait is over, so any thread can run in any order. however after notify but within lock is within lock so even if main thread is executed its locked and can't do anything
My question : shouldn't the control go back to the "Main" thread immediately after line no.31.
You're asking for the impossible. The thread that called notify is still in a synchronized block. Once the other thread finishes waiting, it's back in the synchronized block. So what you are asking for would require two threads to be in synchronized blocks on the same object at once, which is precisely what such blocks prohibit.
synchronized (threadB) {
try {
threadB.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("the total is ====>"+threadB.total);
So this code does this:
Enter synchronized block.
Call wait.
Exit synchronized block.
Print the total.
Notice:
We can't exit the synchronized block unless we're in the synchronized block; and
We can't exit the synchronized block until we return from wait; thus
We can't go from wait to printing the total without being in the synchronized block, thus we cannot do so while another thread remains in the synchronized block or else there would be two threads in the synchronized block at once.
Now look at this code:
notify(); // line no.31
System.out.println("after notify but within lock");
} // exit synchronized block
So any thread that notifies another thread does not leave its synchronized block until after it prints. Thus the notified thread cannot exit its synchronized block until after the print either.
I am trying to achieve this: Created two different threads, one prints odd numbers, one prints even numbers. Once one thread prints a number, it has to wait for the other thread and so on, that is one-after-other.
To achieve this, i am using synchronized block along with wait() and notify().
I am creating a class whose's object will be used to pass to synchronized block in both the threads.
Here is the code:
--> This is used object which will be passed to synchronized block.
package com.vipin.multithread.variousdemos;
public class SyncObject {
public SyncObject () {
}
}
Odd Thread:
package com.vipin.multithread.variousdemos;
public class OddThread implements Runnable {
private Thread t;
int index=0;
SyncObject so=null;
int odd_nums[] = {1,3,5,7,9};
public OddThread(SyncObject so) {
t = new Thread(this,"Odd Thread");
this.so = so;
t.start();
}
public Thread getThreadInstance() {
return t;
}
#Override
public void run() {
while (true) {
synchronized(so) {
System.out.println("Odd num is --->" + odd_nums[index]);
try {
so.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
index++;
so.notify();
if(index>=5) {
return;
}
}
}
}
}
Even Thread: UPDATE
package com.vipin.multithread.variousdemos;
public class EvenThread implements Runnable {
private Thread t;
int index=0;
SyncObject so=null;
int even_nums[] = {2,4,6,8,10};
public EvenThread(SyncObject so) {
t = new Thread(this, "Even thread");
this.so = so;
t.start();
}
public Thread getThreadInstance() {
return t;
}
#Override
public void run() {
while(true) {
synchronized(so) {
System.out.println("Even num is --->" + even_nums[index]);
so.notify(); <-- Here we are notifying.
try {
so.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
index++;
//so.notify(); <-- commented out.
if(index>=5) {
break;
}
}
}
}
}
Main Application:
package com.vipin.multithread.variousdemos;
public class EvenOddDemo {
public static void main(String[] args) throws InterruptedException {
SyncObject so = new SyncObject();
OddThread ot = new OddThread(so);
EvenThread et = new EvenThread(so);
System.out.println("\nIn main thread");
Thread.sleep(1000000000);
System.out.println("Exiting main thread...");
}
}
---> As seen in the code, I am creating two threads to print even and odd numbers. I am using synchronized block, and passing object of type ==> SyncObject.
SyncObject I am passing as argument to these different threads in main.
However, this programs halts, i.e stuck only first statement gets executed, and then it waits forever:
Here is the output:
Odd num is --->1
In main thread
Even num is --->2
I am not able to understand why this program waits for ever, I am using SAME object on which we are invoking synchronized(), wait() and notify(). As per my understanding, it should work, not sure why this is not working.
Any clues as to why this is waiting forever.
UPDATE:
I did some changes in the code, UPDATE and it works fine.
I still have some doubt. Does notify() be called by the thread even if it has not locked the monitor, like in my case after i updated the code.
Sequence of events:
Odd thread gets executed first, then it calls wait() <-- it releases the monitor and now in sleep mode.
Even thread runs, prints msg, and calls notify() <-- here i am not having clear understanding.
When Even thread calls notify(), at that point it has the monitor, so when it calls notify(), does is still own the monitor?
Now, after Even thread calls notify(), then Odd thread gets notified, and hence it starts execution from the point it was sleeping. It is doing some execution and calls notify(), at that points I presume Odd thread is NOT owning the monitor, it calls notify(). So, my question is, does notify() work same whether or not the thread owns the monitor?
It is only when one do the code, one really understands this. I read book and i felt i understood everything, and seems i am back to square one!
The problem here is simply that both threads go straight into wait. Thread 1 gets so, prints value then waits. Thread 2 then gets so, prints value then waits. So both are sleeping away, since nobody is there to notify them. So, a simple fix would be to do so.notify(), right before so.wait(). Then they're not infinitely waiting.
EDIT
Odd thread starts, executes & then waits. Then even thread starts, executes, notifies & then waits. Even thread holds the lock over the monitor until it goes into wait.
When the even thread called on notify, the odd thread awakens & polls for the lock. Once the even thread goes into wait (& releases the lock), then the odd thread can obtain the lock.
If the even thread had not called on notify, then the odd thread would continue to sleep. The even thread would have gone to wait & released the lock. No thread is polling or attempting to obtain the lock, hence the program remains in the suspended state.
The documentation also provides a similar explanation. I hope that clears your doubts.
Is there any use in notify() as the last statement in a sync'd block ?
Eg.: Suppose the following code is running in some thread r,
synchronized(t) {
t.start();
// do stuff using t
t.notify();
}
what would i loose if I remove the line?
t.notify();
Thread r is releasing the lock of t already, and this lock is available to those waiting on it.
The code samples I worked on "behaved" the same with and without the t.notify() call up there.
The only use i can think of is, being somewhat "proactive" in notifying that the monitor of t is being released and those waiting on it will get into BLOCKED state, waiting to acquire it.
However, in this case that notify() is the last statement in the synch'd block, JVM will already know, by exiting the synch'd block, that this lock is released.
This rather is a Q on understanding some specifics on notify() & notifyAll().
TIA.
Please note: I've seen Java notify() run before wait()? and Does the position of the notify() call matter?(Java). This is a different Q than those.
//================================
EDIT: the sample code:
public class T3 {
public static void main(String[] args){
Sum t = new Sum();
synchronized(t) {
t.start();
try {
t.wait();
} catch (InterruptedException ex) {
}
}
System.out.println("Sums up to: " + t.sum);
} // main
}
class Sum extends Thread {
int sum;
public void run() {
synchronized(this) {
for(int i = 1; i <= 55 ; sum += i++);
// notify();
}
}
}
same thing when run() of class Sum is as follows:
public void synchronized run() {
for(int i = 1; i <= 55; sum += i++);
// notify();
}
If you are locking on a thread, and the thread terminates, it sends a notifyAll to whatever threads are waiting on it. 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.
In your example the notification is the last thing done before the thread finishes executing, so the explicit notification is redundant.
(Note that the API documentation quoted here and Jon Skeet are both recommending you don't lock on a thread object.)
Yes. It allows other threads that are wait()ing on t to run again, instead of waiting for a notify that never comes.
Suppose that I have an arraylist called myList of threads all of which are created with an instance of the class myRunnable implementing the Runnable interface, that is, all the threads share the same code to execute in the run() method of myRunnable. Now suppose that I have another single thread called singleThread that is created with an instance of the class otherRunnable implementing the Runnable interface.
The synchornization challenge I have to resolve for these threads is the following: I need all of the threads in myList to execute their code until certain point. Once reached this point, they shoud sleep. Once all and only all of the threads in myList are sleeping, then singleThread should be awakened (singleThread was already asleep). Then singleThread execute its own stuff, and when it is done, it should sleep and all the threads in myList should be awakened. Imagine that the codes are wrapped in while(true)'s, so this process must happen again and again.
Here is an example of the situation I've just described including an attempt of solving the synchronization problem:
class myRunnable extends Runnable
{
public static final Object lock = new Object();
static int count = 0;
#override
run()
{
while(true)
{
//do stuff
barrier();
//do stuff
}
}
void barrier()
{
try {
synchronized(lock) {
count++;
if (count == Program.myList.size()) {
count = 0;
synchronized(otherRunnable.lock) {
otherRunnable.lock.notify();
}
}
lock.wait();
}
} catch (InterruptedException ex) {}
}
}
class otherRunnable extend Runnable
{
public static final Object lock = new Object();
#override
run()
{
while(true)
{
try {
synchronized(lock) {
lock.wait();
} catch (InterruptedException ex) {}
// do stuff
try {
synchronized(myRunnable.lock) {
myRunnable.notifyAll();
}
}
}
}
class Program
{
public static ArrayList<Thread> myList;
public static void main (string[] args)
{
myList = new ArrayList<Thread>();
for(int i = 0; i < 10; i++)
{
myList.add(new Thread(new myRunnable()));
myList.get(i).start();
}
new Thread(new OtherRunnable()).start();
}
}
Basically my idea is to use a counter to make sure that threads in myList just wait except the last thread incrementing the counter, which resets the counter to 0, wakes up singleThread by notifying to its lock, and then this last thread goes to sleep as well by waiting to myRunnable.lock. In a more abstract level, my approach is to use some sort of barrier for threads in myList to stop their execution in a critical point, then the last thread hitting the barrier wakes up singleThread and goes to sleep as well, then singleThread makes its stuff and when finished, it wakes up all the threads in the barrier so they can continue again.
My problem is that there is a flaw in my logic (probably there are more). When the last thread hitting the barrier notifies otherRunnable.lock, there is a chance that an immediate context switch could occur, giving the cpu to singleThread, before the last thread could execute its wait on myRunnable.lock (and going to sleep). Then singleThread would execute all its stuff, would execute notifyAll on myRunnable.lock, and all the threads in myList would be awakened except the last thread hitting the barrier because it has not yet executed its wait command. Then, all those threads would do their stuff again and would hit the barrier again, but the count would never be equal to myList.size() because the last thread mentioned earlier would be eventually scheduled again and would execute wait. singleThread in turn would also execute wait in its first line, and as a result we have a deadlock, with everybody sleeping.
So my question is: what would be a good way to synchronize these threads in order to achieve the desired behaviour described before but at the same time in a way safe of deadlocks??
Based on your comment, sounds like a CyclicBarrier would fit your need exactly. From the docs (emphasis mine):
A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other. The barrier is called cyclic because it can be re-used after the waiting threads are released.
Unfortunately, I haven't used them myself, so I can't give you specific pointers on them. I think the basic idea is you construct your barrier using the two-argument constructor with the barrierAction. Have your n threads await() on this barrier after this task is done, after which barrierAction is executed, after which the n threads will continue.
From the javadoc for CyclicBarrier#await():
If the current thread is the last thread to arrive, and a non-null barrier action was supplied in the constructor, then the current thread runs the action before allowing the other threads to continue. If an exception occurs during the barrier action then that exception will be propagated in the current thread and the barrier is placed in the broken state.