Я иногда использую a volatile
переменная экземпляра в случаях, где я имею два потока, читающие из / пишущий в него, и не хочу издержки (или потенциальный риск мертвой блокировки) вынимания блокировки; например, поток таймера, периодически обновляющий международный идентификатор, который выставляется как метод считывания на некотором классе:
public class MyClass {
private volatile int id;
public MyClass() {
ScheduledExecutorService execService = Executors.newScheduledThreadPool(1);
execService.scheduleAtFixedRate(new Runnable() {
public void run() {
++id;
}
}, 0L, 30L, TimeUnit.SECONDS);
}
public int getId() {
return id;
}
}
Мой вопрос: Учитывая, что JLS только гарантирует, что 32-разрядные чтения будут атомарными, там какая-либо точка в когда-либо использовании энергозависимого долго? (т.е. 64-разрядный).
Протест: не отвечайте высказыванию то использование volatile
synchronized
случай предварительной оптимизации; я хорошо знаю, как / когда использовать synchronized
но существуют случаи где volatile
предпочтительно. Например, при определении боба Spring для использования в однопоточном приложении я склонен одобрять volatile
переменные экземпляра, как нет никакой гарантии, что контекст Spring инициализирует свойства каждого боба в основном потоке.
Не уверен, правильно ли я понял ваш вопрос, но JLS 8.3.1.4. volatile Fields заявляет:
Поле может быть объявлено volatile, и в этом случае модель памяти Java гарантирует, что все потоки видят согласованное значение переменной ( §17.4 ).
и, что, возможно, более важно, JLS 17.7 Неатомарная обработка двойных и длинных :
17.7 Неатомная обработка двойных и длинных
[...]
Для модели памяти языка программирования Java одна запись в энергонезависимое длинное или двойное значение рассматривается как две отдельные записи: по одной в каждую 32-битную половину. Это может привести к ситуации, когда поток видит первые 32 бита 64-битного значения при одной записи, а вторые 32 бита - при другой записи. Запись и чтение изменчивых длинных и двойных значений всегда атомарны. Запись и чтение ссылок всегда атомарны, независимо от того, реализованы ли они как 32- или 64-битные значения.
То есть с помощью модификатора volatile защищается «вся» переменная, а не только две части. Это соблазняет меня утверждать, что даже более важно использовать volatile для long
s, чем для int
s, поскольку даже не читается ] является атомарным для энергонезависимых длинных / двойных позиций.