并发解谜:Java并发 - Cyclicbarrier。正确使用?

时间:2014-04-07 14:10:14

标签: java multithreading concurrency barrier

我正在尝试编写一个程序来解决两个无法独立解决的谜题,但有相同的解决方案。我的想法是,他们都在一个单独的线程中运行,直到他们停止寻找新的信息。然后他们通过更新一些共享状态变量来传达他们发现的内容,并在其中任何一个写入共享状态时继续。

我认为CyclicBarrier是在这里使用的合适机制。这是我的代码(它在两个线程中并发运行:

while (true) {

        doSolvingLogicHere();

        shareUpdates(); // this method updates the shared state variable and is synhronized

        int count;
        int updates = 0;
        try {
            count = writeBarrier.await();
            updates = threadsUpdatedSomething;
            if (count == 0) {
                writeBarrier.reset();
                threadsUpdatedSomething = 0; //'reset' the shared value
            }
        } catch (InterruptedException ex) {
            Logger.getLogger(TwinSolver.class.getName()).log(Level.SEVERE, null, ex);
        } catch (BrokenBarrierException ex) {
            Logger.getLogger(TwinSolver.class.getName()).log(Level.SEVERE, null, ex);
        }
        if (updates == 0) { //no thread updated something
            break;
        } else { // at least one of the threads updated something, solving should continue in both threads
            readUpdates();
        }
}

ThreadsUpdatedSomething是一个共享整数,如果线程更新了任何内容,则会在'ShareUpdates()'中递增。当两个线程在迭代中没有找到任何新内容时,这意味着它们永远不会找到任何新内容,并且应该为两个线程停止整个循环。这就是为什么我要检查它为零。

当两个线程都没有在共享状态变量中写入任何新信息时,我希望它们都停止。但是在运行程序时,其中一个线程停止,而另一个线程继续运行。在调试程序并在'readUpdates()'行设置断点时,程序按预期工作。

这是处理这种并发“解决”循环的正确方法吗?如果它是正确的,我的代码中的错误在哪里?

感谢您的帮助!

编辑:纠正了小错误。 'updates = threadsUpdatedSomething;'现在在正确的地方

1 个答案:

答案 0 :(得分:1)

根据APIawait返回

the arrival index of the current thread, where index getParties() - 1 indicates the first to arrive and zero indicates the last to arrive

 count = writeBarrier.await();

据说,所以只有一个线程会收到0。并且只有一个线程会将updates值设置为0.这就是为什么最后到达的线程停止而其他线程没有停止。

根据您的语句,当您发现两个线程未更新threadsUpdatedSomething时,您需要停止线程。我假设时间threadsUpdatedSomething将为零。 如果不是,你必须改变逻辑,一些如何找到条件必须中断并应用它

while (true) {

        doSolvingLogicHere();

        shareUpdates(); // this method updates the shared state variable and is synhronized

        int count;
        int updates = 0;
        try {
             writeBarrier.await();
            if (threadsUpdatedSomething == 0) {
                updates = threadsUpdatedSomething;
                writeBarrier.reset();
                threadsUpdatedSomething -= 2; //'reset' the counter by decrementing 2
            }
        } catch (InterruptedException ex) {
            Logger.getLogger(TwinSolver.class.getName()).log(Level.SEVERE, null, ex);
        } catch (BrokenBarrierException ex) {
            Logger.getLogger(TwinSolver.class.getName()).log(Level.SEVERE, null, ex);
        }
        if (updates == 0) { //no thread updated something
            break;
        } else { // at least one of the threads updated something, solving should continue in both threads
            readUpdates();
        }
}

如果需要,也不要忘记在例外情况下设置休息条件。