我在并发性方面的经验很明显,我正在寻找一些帮助。
我正在用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启动线程2
- 线程2做一些事情,但没有完成任务
- 线程1读取taskCompleted为false
- 线程2完成任务,引发taskCompleted标志,并通知(nobody) 线程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