本文介绍了使用CountDownLatch时如何正确同步/锁定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

它归结为通过某种服务提交一个线程的工作.作业在某些TPExecutor中执行.之后,此服务将检查结果,并在某些情况下(作业超出最大重试次数等)在原始线程中引发异常.下面的代码段用遗留代码粗略地说明了这种情况:

It boils down to one thread submitting job via some service. Job is executed in some TPExecutor. Afterwards this service checks for results and throw exception in original thread under certain conditions (job exceeds maximum number of retries, etc.). Code snippet below roughly illustrate this scenario in legacy code:

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核心服务器机器上发生)异常未报告给原始线程.我认为这是因为没有强制发生-before-before(例如,"countDown"发生在"setThrowable"之前),并且程序继续工作(但应该失败).对于如何解决此问题,我将不胜感激.限制条件是:一周内发布,对现有代码库的影响最小.

Sometimes, (not reproducible on my box, but happens on 16 core server box) exception isn't getting reported to original thread. I think this is because happens-before is not forced(eg. 'countDown' happens before 'setThrowable') and program continues to work(but should fail).I would appreciate any help about how to resolve this case.Constraints are: release in a week, minimum impact on existing codebase is needed.

推荐答案

上面的代码(现在已更新)应该可以按预期工作,而无需使用其他同步机制.通过使用CountDownLatch await()countdown()方法来强制执行内存屏障及其相应的在发生之前" 关系.

The code above (as now updated) should work as you expected without the use of further synchronisation mechanisms. The memory barrier and its corresponding 'happens-before' relationship is enforced by the use of the CountDownLatch await() and countdown() methods.

来自 API文档:

如果您定期处理并发,请给自己一份实践中的Java并发性" ,它是Java并发性圣经,非常值得在您的书架上加重:-).

If you are dealing with concurrency on a regular basis get yourself a copy of 'Java Concurrency in Practice', it's the Java concurrency bible and will be well worth its weight on your bookshelf :-).

这篇关于使用CountDownLatch时如何正确同步/锁定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-03 21:23
查看更多