是否可能存在等待线程完成任务的竞争条件?



我在并发性方面的经验很明显,我正在寻找一些帮助。

我正在用Java编写一个多线程应用程序,这时我被一个疑问所困扰。请看下面的示例代码(混合伪代码和Java):

标题1正文(部分):

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

标题2正文:

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开始等待。而且永远不会结束。

请让我知道如果你有任何想法和/或这是一个众所周知的场景(完全重复?)

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
    }
  }
}

我认为这些块应该同步,参见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

除了其他人之前的回答之外,根据我的个人经验,尽可能避免使用wait, notify等(除非您正在构建自定义同步器)。有许多好的和足够的类,如信号量、屏障、闩锁、锁或通用同步。它们在90%的情况下是足够的。在上述情况下,您可以使用synchonized(this)或任何其他变量。或者可以使用ReenterantLock

最新更新