Есть ли какая-либо точка в использовании энергозависимого долго?

Я иногда использую 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 инициализирует свойства каждого боба в основном потоке.

53
задан aioobe 22 November 2010 в 22:15
поделиться

1 ответ

Не уверен, правильно ли я понял ваш вопрос, но 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, поскольку даже не читается ] является атомарным для энергонезависимых длинных / двойных позиций.

123
ответ дан 7 November 2019 в 08:25
поделиться