0

Please follow the code below,

Resource.java,

public class Resource {

public void first() {

    Thread t = Thread.currentThread();
    try {
        System.out.println(t.getName() + " : is accessing the method 'first' ");

        synchronized (this) {
            for (int num = 1; num <= 10; num++) {
                System.out.println(t.getName() + " : NUM : " + num);
                Thread.sleep(500);
                if (num == 5) {
                    this.wait();
                }
            }
            this.notify();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

}

public void second() {

    Thread t = Thread.currentThread();
    try {
        System.out.println(t.getName() + " : is accessing the method 'second' ");

        synchronized (this) {
            for (int num = 1; num <= 10; num++) {
                System.out.println(t.getName() + " : X : " + num);
                Thread.sleep(500);
                if (num == 7) {
                    this.notify();
                    this.wait();                       
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

}
}

ReqThread.java as follows,

public class ReqThread extends Thread{

public ReqThread(String name,Resource res){
    this.setName(name);
    this.res = res;
}

private Resource res;

@Override
public void run(){
    try{
        if("ONE".equals(this.getName())){
            res.first();
        }else{
            res.second();
        }            
    }catch(Exception e){
        e.printStackTrace();
    }
}
}

And MainClass.java,

public class MainClass {
public static void main(String [] args){
    Resource res = new Resource();
    ReqThread t1 = new ReqThread("ONE", res);
    ReqThread t2 = new ReqThread("TWO", res);

    t1.start();
    t2.start();
}
}

You can see from the above code, i am trying to learn on thread communication using wait and notify mechanism.

Here one the thread 'ONE' starts first starts, than an counter 5 waits and releases the lock, and than thread 'TWO' proceeds (which was already in the waiting state) and than its counter reaches 7 notifies and waits.

So my question is when thread 'TWO' do notify in method 'second', does is releases the lock ?

the output of the above code is

ONE : is accessing the method 'first' 
ONE : NUM : 1
TWO : is accessing the method 'second' 
ONE : NUM : 2
ONE : NUM : 3
ONE : NUM : 4
ONE : NUM : 5
TWO : X : 1
TWO : X : 2
TWO : X : 3
TWO : X : 4
TWO : X : 5
TWO : X : 6
TWO : X : 7
ONE : NUM : 6
ONE : NUM : 7
ONE : NUM : 8
ONE : NUM : 9
ONE : NUM : 10
TWO : X : 8
TWO : X : 9
TWO : X : 10

Now, if I do the code change in Resource.java in method 'second' as below

if (num == 7) {
                    this.notify();
                    //this.wait();                       
                }

the output of the code is

ONE : is accessing the method 'first' 
ONE : NUM : 1
TWO : is accessing the method 'second' 
ONE : NUM : 2
ONE : NUM : 3
ONE : NUM : 4
ONE : NUM : 5
TWO : X : 1
TWO : X : 2
TWO : X : 3
TWO : X : 4
TWO : X : 5
TWO : X : 6
TWO : X : 7
TWO : X : 8
TWO : X : 9
TWO : X : 10
ONE : NUM : 6
ONE : NUM : 7
ONE : NUM : 8
ONE : NUM : 9
ONE : NUM : 10

From the second output you can see, even if thread 'TWO' does notify(), than too it doesn't waits and continues its printing numbers,

is this because even if thread 'TWO' does notify() but than too the code is still in synchronized block, and it still has the lock which is not yet released ?

1 Answer 1

2

The answer is in the javadoc. Object#notify() states

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;

So you are correct. Calling object.notify() doesn't release the object's monitor. It simply wakes up a thread which still needs to compete to get it.

So notify() doesn't release the monitor, but wait() does.

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.


When you are comfortable with how object synchronization and wait() and notify() work, consider moving to the java.util.concurrent package which does all this for you.

Sign up to request clarification or add additional context in comments.

1 Comment

+1 and this competition for the lock after a thread has been notified is specifically the reason why we have race conditions around multiple producer/consumer implementations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.