Синхронизировать метод ScheduledFuture.cancel()
Приведенный ниже код вырезан из книги "Программирование параллелизма на JVM: освоение синхронизации, STM и актеры"
Я не понимаю, почему автор синхронизирует метод stopEnergySource, который просто отменяет задачу ScheduledFuture, которая представлена переменной replenishTask? Нет других методов, которые используют эту переменную. Желательно ли практиковать синхронизацию вызовов 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() {
//...
}
}
1 ответ
Нет других методов, которые используют эту переменную. Желательно ли практиковать синхронизацию вызовов Future.cancel или это просто необходимо для ScheduledFuture?
Я считаю, что автор кода пытается создать барьеры памяти в случае, если другой поток пытается вызвать stopEnergySource()
это начало работу в первую очередь.
Однако, если это было так, то init()
метод также должен быть synchronized
потому что они не делают безопасную публикацию replenishTask
поле. Это поле не final
и компилятор может иметь create(...)
вернуться, но продолжить строительство и инициализацию EnergySource
возразить позже.
Если бы несколько потоков создавали и останавливали эти объекты, вы могли бы легко получить NPE в stopEnergySource(...)
даже с synchronized
Ключевое слово на нем.