0

我有一种方法,我尝试使用 GPARS 并行化计算并计算调用中的聚合布尔“和”结果。此方法被包装为 @ActiveObject ,它将结果作为数据流传递 - 下面的代码具有我尝试使用 AtomicBoolean 存储聚合以保护它的原始方法。

这在计算出的“最终真相”上不起作用(有时我的测试会通过其他他们会失败的测试)。为了解决这个问题,我从 AtomicBoolean 更改为 Agent(boolean) 方法,我认为它已经“修复”了它——至少我的 spock 测试一直在成功。

尝试使用 AtomicBoolean 构建最终结果时,我的逻辑在哪里存在缺陷?感觉它应该工作 - 但没有,我不明白为什么。

下面的方法 - 我把原始版本和更正的版本放在下面

@ActiveMethod
def evaluateAllAsync () {
    AtomicBoolean result = new AtomicBoolean(true)
    GParsPool.withPool {
        // do as parallel 
        conditions.eachParallel { condition ->
            println "evalAllAsync-parallel intermediate result start value is ${result.get()} and condition with expression ${condition.expression} evaluated to ${condition.evaluate()}"
            result.getAndSet(result.get() && condition.evaluate())
            println "recalc bool value is now ${result.get()}"
        }
    }
    println "evalAllAsync-parallel final result value is ${result.get()}"
    result.get()

}

通过使用像这样的代理表单修复了问题

@ActiveMethod
def evaluateAllAsync () {
    def result = new Agent (true)
    GParsPool.withPool {
        // do as parallel 
        conditions.eachParallel { condition ->
            println "evalAllAsync-parallel intermediate result start value is ${result.val} and condition with expression ${condition.expression} evaluated to ${condition.evaluate()}"
            result << { def res = it && condition.evaluate(); println "start> $it and finish> $res"; updateValue(res)}
            println "recalc bool value is now ${result.val}"
        }
    }
    println "evalAllAsync-parallel final result value is ${result.val}"
    result.val

}

我把 debug println 放在这里,这样我就可以看到代码在做什么。

具有保护布尔聚合值的代理的版本似乎正在运行。

为什么原子布尔值不起作用?

4

1 回答 1

0

好吧,这是您如何使用 AtomicBoolean 的问题。您总是强行覆盖(getAndSet())存储在其中的值,并忽略其他线程可能在当前线程忙于“评估”时更改它的可能性。

您可能想改用 compareAndSet() 方法:

    def valueToUse = result.get()
    result.compareAndSet(valueToUse, valueToUse && condition.evaluate())
于 2016-12-02T14:59:33.347 回答