Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
190 views
in Technique[技术] by (71.8m points)

multithreading - Behavior of wait() and notifyAll() in Java?

Please note that this is not the actual scenario. I created a sample scenario based on my actual implementation, to make it easy to review. I am also already getting the expected output too. However, I need to clarify some concepts regarding the wait() and notifyAll() methods in Java. (In here both these threads will starts there run method at once in the main thread.) So according to my knowledge, since thread B is sleeping, because you can see at the initial stage reamingCount is 400.

So thread B will calls its MUTEX.wait() and continue its sleep until some other thread invokes a notify() or notifyAll(), then after the remainingCount decrements to 0, thread A will call MUTEX.notifyAll(); to awake the thread B and MUTEX.wait() to release its already granted lock, and go to sleep until thread B notifies it.

When I call MUTEX.notifyAll() through thread A, won't thread B wake up and continue its task before thread A calls MUTEX.wait()?

I mean, you can see when thread A calls the MUTEX.notifyAll(), thread B will awake and check again if the condition in the while loop is true or false. So, since the remainingCount is equal to 0, thread B will exit the while loop and continue its task before thread A calls wait(). Won't this scenario break the principle of wait()? According to my knowledge thread B can only continue its execution when thread A calls wait().

public class A implements Runnable{

    public static volatile remainingCount =400;
    private final Object MUTEX;//Both class A and B holds the same object mutex

    private void methodA(){

         synchronized(MUTEX){
             
              while(remainingCount == 0){

                     MUTEX.notifyAll();
                     MUTEX.wait();
              }

              //Perform it's usual task.In here remaining count will decrement during the process.
              

        }
      @Override
      public void run() {

        while(true){
          methodA();
        }
     }
   }
}
public class B implements Runnable{

         private final Object MUTEX;//Both class A and B holds the same object mutex

         private void methodB(){
              synchronized(MUTEX){

                   while (A.remainingCount != 0) {
                        try {
                    
                               MUTEX.wait();
                     
                        } catch (InterruptedException ex) {
                               Logger.getLogger(InkServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
                        }
                   }
                      //incrementing the A.remainingCount 

                      MUTEX.notifyAll();
 
            }
            
           @Override
           public void run() {

                  while(true){
                     methodB();

                   }
             }
}

question from:https://stackoverflow.com/questions/65651597/behavior-of-wait-and-notifyall-in-java

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

When a thread holding a lock calls wait() on the locked object, the thread is added to the object's wait set and the lock is released.

When a thread holding a lock calls notify(), and the wait set is not empty, a thread in the wait set is selected and removed. Likewise, calling notifyAll() removes all threads from the wait set.

Note: threads can also be removed from the wait set by a call to thread.interrupt().

When a thread is removed from the wait set and begins to run, the first step is to reacquire the lock. This happens before the return from wait().

This will not happen until the thread that called notify() or notifyAll() releases the lock by either calling wait() or exiting the synchronized block.

So, while your thread B has been enabled to run, it won't actually return from wait() until thread A releases the lock by calling MUTEX.wait(). Likewise, thread A is enabled to run when B calls MUTEX.notifyAll(), but doesn't return from wait() until thread B exits the synchronized(MUTEX) block.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...