【问题标题】:Thread not printing everything after notifyAll in javajava中的notifyAll之后线程不打印所有内容
【发布时间】:2014-10-07 19:27:04
【问题描述】:
class Lock implements Runnable{
  int i=0;
  public synchronized void run(){
    for(i=0;i<10;i++){
        if(Thread.currentThread().getName().equals("t1") && i == 5)
         {try { this.wait();} catch(InterruptedException ie){}}
        System.out.print(Thread.currentThread().getName()+" ");
        if(Thread.currentThread().getName().equals("t3") && i == 9)
         this.notifyAll();
  }
 }
}
public class ThreadLock {
 public static void main(String[] args){   
  Lock l = new Lock();
  Thread t1 = new Thread(l);
  Thread t2 = new Thread(l);
  Thread t3 = new Thread(l);
  t1.setName("t1");
  t2.setName("t2");
  t3.setName("t3");
  t1.start();
  t2.start();
  t3.start();
 }
}

输出是: t1 t1 t1 t1 t1 t3 t3 t3 t3 t3 t3 t3 t3 t3 t3 t1 t2 t2 t2 t2 t2 t2 t2 t2 t2 t2

调用 notifyAll 方法后,t1 未打印全部 10 次。 我运行了很多次,但每次 t1 只打印 6 次。 为什么 t1 没有全部打印 10 次? 请尽快回复

【问题讨论】:

  • 即使您已将i 更改为局部变量,该程序也不能保证始终打印“t1”十次。理论上,t3 线程有可能在 t1 任务调用wait() 之前完成其任务并调用notifyAll()。如果发生这种情况,wait() 调用将永远不会返回。

标签: java multithreading wait synchronized notify


【解决方案1】:

i 是一个实例变量。它由所有线程共享。它应该是一个局部变量。

当第一个线程被唤醒时,它重新获取锁,打印它的名字,增加 i,并重新评估是否为i &lt; 10。但由于其他线程已经将i 设置为 10,因此循环停止。

【讨论】:

    【解决方案2】:

    问题是你在线程之间共享相同的索引i,所以当线程t3存在并且t1被唤醒时索引i将是10并且线程t1中的for循环将退出。

    【讨论】:

      【解决方案3】:

      在启动每个线程后尝试在每个线程上调用 .join() 以确保每个线程在程序退出之前完成?

      【讨论】:

      • 任何活动的非守护线程都应该阻止 jvm 终止,但是当 main 返回时可以关闭 stdout。
      【解决方案4】:

      虽然 JB Nizet 已经给出了正确答案,但您可能想知道,为什么这只影响t1: 当调用 run 方法(同步的)时,每个线程都在重置 i

      但是当你返回 t1 的执行时 - 它不会重置 i,因为线程已经启动了 for-loop。

         i | output
         0 | t1 (FIRST iteration of t1 -> Setting i=0)
         1 | t1
         2 | t1
         3 | t1
         4 | t1
         5 | t1
         0 | t3 (FIRST iteration of t3 -> Setting i = 0)
         1 | t3
         2 | t3
         3 | t3
         4 | t3
         5 | t3
         6 | t3
         7 | t3
         8 | t3
         9 | t3
         0 | t2 (FIRST iteration of t2 -> Setting i = 0)
         1 | t2
         2 | t2
         3 | t2
         4 | t2
         5 | t2
         6 | t2
         7 | t2
         8 | t2
         9 | t2
         9 | t1 (t1 restored, but i=9 now. One more output, program done)
      

      注意:这至少是您描述的输出所发生的情况。我认为也有可能,t2 在 t3 之前执行,导致不同的输出。

      【讨论】:

      • 谢谢。我知道了。 'i' 在同步方法之外,所以现在我创建了 for 循环的 'i' 局部变量。 'for(int i=0;i
      猜你喜欢
      • 1970-01-01
      • 2011-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-25
      • 2020-01-06
      • 2015-12-20
      相关资源
      最近更新 更多