Code below是来自"Programming Concurrency on the JVM: Mastering Synchronization, STM, and Actors" book
的示例我不明白为什么作者同步 stopEnergySource 方法,它只是取消了由 replenishTask 变量代表的ScheduledFuture任务?没有其他方法可以使用此变量。 是否需要同步Future.cancel调用或者它只需要ScheduledFuture?
public class EnergySource {
//...
private static final ScheduledExecutorService replenishTimer =
Executors.newScheduledThreadPool(10);
private ScheduledFuture<?> replenishTask;
private EnergySource() {}
private void init() {
replenishTask = replenishTimer.scheduleAtFixedRate(new Runnable() {
public void run() { replenish(); }
}, 0, 1, TimeUnit.SECONDS);
}
public static EnergySource create() {
final EnergySource energySource = new EnergySource();
energySource.init();
return energySource;
}
public long getUnitsAvailable() {
//...
}
public long getUsageCount() {
//...
}
public boolean useEnergy(final long units) {
//...
}
public synchronized void stopEnergySource() { // what for **synchronized** is?
replenishTask.cancel(false);
}
private void replenish() {
//...
}
}
答案 0 :(得分:0)
没有其他方法可以使用此变量。是否需要同步Future.cancel调用或者它只需要ScheduledFuture?
我相信代码的作者试图强制内存障碍,以防不同的线程试图首先调用stopEnergySource()
启动作业。
但是,如果是这种情况,那么init()
方法应该也为synchronized
,因为他们没有安全发布replenishTask
字段。该字段不是final
,并且允许编译器返回create(...)
,但稍后继续构造和初始化EnergySource
对象。
如果多个线程正在创建并停止这些对象,您可以轻松地在stopEnergySource(...)
中获取NPE,即使其上包含synchronized
关键字。