我有以下类将被多个线程使用:

public class Container

    private volatile Date date;
    private int amount;
    private final Object lock = new Object();

    public void update(int amount){
        int actualAmount;
        if(check(date)){
              //do some BULK computation to compute the actualAmount
             synchronized(lock){
                 date = new Date();
                 this.amount = actualAmount;
             }
        }
    }

    private boolean check(Date date){
        synchronized(lock){
          //reading from the date and returning true if the date is expired
        }
    }
}

但我不确定正确性。首先,我将 Date 字段声明为 volatile 以在执行条件检查时观察变化。但是可能会发生在进行批量计算时,第二个线程试图执行导致数据竞争的更新。

我不想将 BULK 计算放入同步块(synchronized block)中,因为它包括调用几个外来方法并阻止 JVM 进行优化。

执行两次批量计算不会对数据结构造成损害,但会浪费处理器的时间。

我应该如何以更有效的方式处理这个问题?

最佳答案

当批量计算完成并且另一个线程在此期间更改了数量时,我们别无选择,只能重新计算数量(重新运行此批量操作),是吗?

    public void update(int amount) {
    int actualAmount;
    if (check(date)){
          //do some BULK computation to compute the actualAmount
         synchronized(lock) {
            if (check(date)) {
                 date = new Date();
                 this.amount = actualAmount;
            } else {
                update(amount);
            }
         }
    }
}

当两个线程执行此批量操作并且其中一个应该再次重新运行时,这不是浪费 CPU 时间吗?

累积这个更新(数量)可能更有效,当某个线程需要读取正确的数量时,然后重新计算它(运行批量操作)。

什么线程会读到这么多?它需要最新的信息吗?
知道答案可能有助于设计更好的解决方案。

更新 1。
顺便说一句,这种递归重新计算可能需要一遍又一遍。所以最正确的方法是将整个 update() 主体包装到 synchronized 语句中。

10-07 19:15
查看更多