【问题标题】:Behavior of wait() and notifyAll() in Java?Java 中 wait() 和 notifyAll() 的行为?
【发布时间】:2021-01-10 09:01:12
【问题描述】:

请注意,这不是实际情况。我根据我的实际实现创建了一个示例场景,以便于查看。我也已经得到了预期的输出。但是,我需要澄清一些关于Java 中wait()notifyAll() 方法的概念。 (在这里,这两个线程都会在主线程中同时启动 run 方法。)所以据我所知,由于线程 B 处于休眠状态,因为您可以在初始阶段看到 reamingCount 为 400。

所以线程 B 会调用它的 MUTEX.wait() 并继续休眠,直到其他线程调用 notify()notifyAll(),然后在剩余计数减为 0 后,线程 A 将调用 MUTEX.notifyAll(); 唤醒线程 B和MUTEX.wait() 释放它已经授予的锁,并进入睡眠状态,直到线程B通知它。

当我通过线程A调用MUTEX.notifyAll()时,线程B不会在线程A调用MUTEX.wait()之前唤醒并继续其任务吗?

我的意思是,你可以看到当线程 A 调用 MUTEX.notifyAll() 时,线程 B 将唤醒并再次检查 while 循环中的条件是真还是假。因此,由于剩余计数等于 0,线程 B 将退出 while 循环并在线程 A 调用 wait() 之前继续其任务。这种情况不会破坏wait()的原则吗?据我所知,只有当线程A调用wait()时,线程B才能继续执行。

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();

                   }
             }
}

【问题讨论】:

    标签: java multithreading concurrency java-threads


    【解决方案1】:

    当持有锁的线程在被锁定的对象上调用wait()时,该线程被添加到对象的等待集中并释放锁。

    当持有锁的线程调用notify(),且等待集不为空时,选择并移除等待集中的线程。同样,调用notifyAll() 会从等待集中删除所有线程。

    注意:线程也可以通过调用thread.interrupt()从等待集中移除。

    当一个线程从等待集中移除并开始运行时,第一步是重新获取锁。这发生在从wait() 返回之前。

    在调用notify()notifyAll() 的线程通过调用wait() 或退出同步块释放锁之前,不会发生这种情况。

    因此,当您的线程 B 已启用运行时,它实际上不会从 wait() 返回,直到线程 A 通过调用 MUTEX.wait() 释放锁。同样,线程 A 在 B 调用 MUTEX.notifyAll() 时可以运行,但在线程 B 退出 synchronized(MUTEX) 块之前不会从 wait() 返回。

    【讨论】:

    • 非常感谢您回答我的问题。
    猜你喜欢
    • 2012-07-08
    • 1970-01-01
    • 2011-09-11
    • 2018-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-18
    • 2013-02-23
    相关资源
    最近更新 更多