我有以下类将被多个线程使用:
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 语句中。