这种竞争条件是否有可能等待线程完成任务?

时间:2011-09-08 13:27:40

标签: java concurrency race-condition

我对并发性的经验非常清楚,我在这里寻求帮助。

我正在编写一个Java的多线程应用程序,而我却被怀疑。请查看此示例代码(混合伪代码和Java):

Thead 1 body(部分)

/* It creates and starts thread Thread 2 */
if (!thread2.taskCompleted)
   thread2.wait();
/* continue execution... */

Thead 2 body

class Thread2 extends Thread {

    volatile boolean taskCompleted = false;

    public void run() {
        /* It executes a complex task... */
        taskCompleted = true;
        notifyAll(); // notify waiting threads
    }

}

我担心的很简单:如果语句按此顺序执行会发生什么:

  1. 线程1启动线程2
  2. 线程2做了一些事情,但没有完成任务
  3. 线程1将taskCompleted读为false
  4. 线程2完成任务,引发taskCompleted标志,并通知(nobody)
  5. 线程1开始等待。永远不会结束。
  6. 如果您有任何想法和/或这是一个众所周知的场景(完全重复?),请告诉我。

3 个答案:

答案 0 :(得分:2)

我认为应该同步这些块,请参阅http://download.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html

或者您可以使用类似CountDownLatch的内容,请参阅:http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/CountDownLatch.html

答案 1 :(得分:2)

taskCompleted标记和wait()/nofiyAll() 的使用必须受锁保护,以避免您描述的情况。

/* It creates and starts thread Thread 2 */
synchronized (thread2) {
  if (!thread2.taskCompleted)
    thread2.wait();
}
/* continue execution... */

class Thread2 extends Thread {

  boolean taskCompleted = false;

  public void run() {
    /* It executes a complex task... */
    synchronized (this) {
      taskCompleted = true;
      notifyAll(); // notify waiting threads
    }
  }
}

答案 2 :(得分:1)

除了别人之前回答的问题之外,根据我的个人经验,尽可能避免使用等待,通知等等(除非你正在构建自定义同步器)。有许多好的和充足的类,如信号量,屏障,闩锁,锁定或一般同步。 他们在90%的情况下都足够了。 在上面的例子中,你可以使用synchonized(this)或任何其他变量。 或者可以使用ReenterantLock