【发布时间】:2010-12-04 09:21:23
【问题描述】:
归结为一个线程通过某个服务提交作业。 Job 在一些 TPExecutor 中执行。之后,此服务在某些条件下(作业超过最大重试次数等)检查结果并在原始线程中抛出异常。下面的代码 sn-p 大致说明了遗留代码中的这种情况:
import java.util.concurrent.CountDownLatch;
public class IncorrectLockingExample {
private static class Request {
private final CountDownLatch latch = new CountDownLatch(1);
private Throwable throwable;
public void await() {
try {
latch.await();
} catch (InterruptedException ignoredForDemoPurposes) {
}
}
public void countDown() {
latch.countDown();
}
public Throwable getThrowable() {
return throwable;
}
public void setThrowable(Throwable throwable) {
this.throwable = throwable;
}
}
private static final Request wrapper = new Request();
public static void main(String[] args) throws InterruptedException {
final Thread blockedThread = new Thread() {
public void run() {
wrapper.await();
synchronized (wrapper) {
if (wrapper.getThrowable() != null)
throw new RuntimeException(wrapper.getThrowable());
}
}
};
final Thread workingThread = new Thread() {
public void run() {
wrapper.setThrowable(new RuntimeException());
wrapper.countDown();
}
};
blockedThread.start();
workingThread.start();
blockedThread.join();
workingThread.join();
}
}
有时,(在我的机器上无法重现,但在 16 核服务器机器上发生)异常不会被报告给原始线程。我认为这是因为没有强制发生之前发生(例如,'countDown' 发生在 'setThrowable' 之前)并且程序继续工作(但应该失败)。 我将不胜感激有关如何解决此案的任何帮助。 限制条件是:一周内发布,需要对现有代码库的影响最小。
【问题讨论】:
-
250 KLOC 项目在这里完全多线程,在 16 核等上工作。我们使用“高级”多线程工具,如 CountDownLatch 一个 lot。我们使用 Object 的 wait() 方法和 Thread 的 join() 等低级事物的次数i> 方法? 零。在我看来,现在默认 API 中有足够的高级并发设施,您不需要重新发明基于 Java 特质的任何损坏的轮子。 +1 彼得劳里的回答。
-
@Webinator:OP is 使用“高级”
CountDownLatch工具来实现其设计目的之一。 -
您确定上面的代码没有按预期运行吗?在您进行更正后,我认为没有理由不这样做。
-
我没有意识到 wait() 是一个坏轮子/
标签: java multithreading locking blocking