1

I am trying to use wait() and notify() on a class to notify the waiting thread but the scenario is whoever go first into the synchronized block will wait for other to print some values and notify the waiting thread. but the waiting thread is keep waiting. what am doing wrong.

public class MyRunnableClass implements Runnable {
public static boolean transfer = false;
public static boolean isAnyThreadWaiting = false;

int a=10;
@Override
public void run() {
    // TODO Auto-generated method stub

    synchronized(this) {    
        System.out.println("I am Thread : "+Thread.currentThread().getName()+" and I first occuipied block");
        
        try {
            if(isAnyThreadWaiting)
                MyRunnableClass.transfer=true;

            if(!MyRunnableClass.transfer&&!isAnyThreadWaiting) {
                System.out.println("I am Thread : "+Thread.currentThread().getName()+" and I am going to wait");
                while(!MyRunnableClass.transfer) {
                    isAnyThreadWaiting=true;
                    this.wait();
                }
                
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        for(int i=0; i<a;i++) {
            System.out.println("I am Thread : "+Thread.currentThread().getName()+" Value of  a is : "+i );
            
        }
        a=0;
        isAnyThreadWaiting=false;
        
        this.notify();
    
        
    }
    
}

public static void main(String [] args) throws InterruptedException {
MyRunnableClass runnable1= new MyRunnableClass();
Thread thread1=new Thread(runnable1,"t1");
Thread thread2=new Thread(runnable1,"t2");
    thread1. start();
    
    
    
    thread2. start();
    }
}
VGR
  • 40,506
  • 4
  • 48
  • 63
ImI
  • 198
  • 1
  • 8
  • Here is some information regarding wait() and notify(): https://ducmanhphan.github.io/2019-12-07-Using-wait-notify-in-synchronized-method-block-of-Multithreading-Java/ According to this article, your wait() and notify() seems to be fine. So the problem is most probably in your static variables (see my answer) – Mykhailo Skliar Jun 02 '21 at 16:24

3 Answers3

2
synchronized(this)

this is the same in both of your threads, since you used the same Runnable instance. synchronized ensures that two threads can't be inside the block at the same time. Which means one thread is sitting at the beginning of the synchronized block and the other is sitting at wait. You need to narrow your synchronization down to the places you actually use shared state, i.e. only synchronized(this) the code that actually references (reads or writes) the variables that both threads need.

Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
  • When you call wait(), you release the lock and your thread waits, until notify() method of the other thread is called. In other words, when you call wait(), synchronized block becomes available to other threads, until the current thread leaves "wait" state and grabs the lock again. So, it is actually quite the opposite of what you say: on the contrary, you need to ensure that any calls to wait() or notify() are within a synchronized region of code (with the wait() and notify() calls being synchronized on the same object). – Mykhailo Skliar Jun 02 '21 at 16:00
1

I have debugged your code and found the reason:

a=0;

Please, remove this code and you will see the output of both threads:

I am Thread : t1 and I first occuipied block
I am Thread : t1 and I am going to wait
I am Thread : t2 and I first occuipied block
I am Thread : t2 Value of  a is : 0
I am Thread : t2 Value of  a is : 1
I am Thread : t2 Value of  a is : 2
I am Thread : t2 Value of  a is : 3
I am Thread : t2 Value of  a is : 4
I am Thread : t2 Value of  a is : 5
I am Thread : t2 Value of  a is : 6
I am Thread : t2 Value of  a is : 7
I am Thread : t2 Value of  a is : 8
I am Thread : t2 Value of  a is : 9
I am Thread : t1 Value of  a is : 0
I am Thread : t1 Value of  a is : 1
I am Thread : t1 Value of  a is : 2
I am Thread : t1 Value of  a is : 3
I am Thread : t1 Value of  a is : 4
I am Thread : t1 Value of  a is : 5
I am Thread : t1 Value of  a is : 6
I am Thread : t1 Value of  a is : 7
I am Thread : t1 Value of  a is : 8
I am Thread : t1 Value of  a is : 9

P.S. Second thread in your example actually doesn't go to the wait() state.

But because you set a to 0 by the second thread, the first thread skips this cycle:

for(int i=0; i<a;i++) {
    System.out.println("I am Thread : "+Thread.currentThread().getName()+" Value of  a is : "+i );
    
}

That's why you don't see the output by the first thread. But it isn't stuck in the wait() state.

Mykhailo Skliar
  • 1,242
  • 1
  • 8
  • 19
  • I've made a small mistake in this answer: first thread actually do goes to the wait() state, but the second doesn't. I edited the answer, now it looks more correct. – Mykhailo Skliar Jun 03 '21 at 10:17
0

Changes made to static variables in one thread are not visible to the other thread. Therefore, for both threads, it is always transfer == false and isAnyThreadWaiting == false.

This means that both threads go to "wait()" block and stuck there forever.

Because you are trying to synchronize on the static variables, you would have to use synchronized static method.

See more details here: How to synchronize a static variable among threads running different instances of a class in Java?

But the simpler solution would be not to use static variables at all. In your case, you use the same object for both threads, so making variables static is not necessary anyway:

private boolean transfer = false;
private boolean isAnyThreadWaiting = false;

The complete solution should look like this:

public class MyRunnableClass implements Runnable {
private boolean transfer = false;
private boolean isAnyThreadWaiting = false;

int a=10;

@Override
public void run() {
    // TODO Auto-generated method stub

    synchronized(this) {    
        System.out.println("I am Thread : "+Thread.currentThread().getName()+" and I first occuipied block");
        
        try {
            if(isAnyThreadWaiting)
                transfer=true;

            if(!transfer && !isAnyThreadWaiting) {
                System.out.println("I am Thread : "+Thread.currentThread().getName()+" and I am going to wait");
                while(!transfer) {
                    isAnyThreadWaiting=true;
                    this.wait();
                }
                
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        for(int i=0; i<a;i++) {
            System.out.println("I am Thread : "+Thread.currentThread().getName()+" Value of  a is : "+i );
            
        }
        a=0;
        isAnyThreadWaiting=false;
        
        this.notify();
    
        
    }
    
}

public static void main(String [] args) throws InterruptedException {
MyRunnableClass runnable1= new MyRunnableClass();
Thread thread1=new Thread(runnable1,"t1");
Thread thread2=new Thread(runnable1,"t2");
    thread1. start();
    
    
    
    thread2. start();
    }
}
Mykhailo Skliar
  • 1,242
  • 1
  • 8
  • 19
  • I have tried this but same is the result . thread1 wait for the notify() and t2 is printing values but not waking up the thread1 result: I am Thread : t1 and I first occuipied block I am Thread : t1 and I am going to wait I am Thread : t2 and I first occuipied block I am Thread : t2 Value of a is : 0 I am Thread : t2 Value of a is : 1 I am Thread : t2 Value of a is : 2 I am Thread : t2 Value of a is : 3 I am Thread : t2 Value of a is : 4 I am Thread : t2 Value of a is : 5 I am Thread : t2 Value of a is : 6 I am Thread : t2 Value of a is : 7 – ImI Jun 02 '21 at 17:24