読者です 読者をやめる 読者になる 読者になる

long と double に対する volatile 修飾子

数年前、「long と double は JVM 実装によっては二つの 32bit 値として扱うことがあるので、volatile 修飾子では atomic 性を確保できない。synchronized を使わないとスレッドセーフにならない」という話になったことがある。

最近、『Java の理論と実践』シリーズを読んでいて、上記の話題を思い出したのだが、「そういえば long や double は volatile 修飾子でスレッドセーフ性は確保できないという話はでてこないな」と思って調べ直してみた。

結論

long も double も volatile 修飾子によって読み書きの atomic 性を保障できる。

すなわち、以下の LongVariable クラスはスレッドセーフである。

class LongVariable {
  private volatile long i = 0;

  void setValue(long j) {
    i = j;
  }

  long  getValue() {
    return i;
  }
}

ソース

The Java® Language Specification 17.7. Non-atomic Treatment of double and long より。

Writes and reads of volatile long and double values are always atomic.

Writes to and reads of references are always atomic, regardless of whether they are implemented as 32-bit or 64-bit values.

すなわち、

  • volatile の long と double の読み書きは常に atomic である
  • 32 bit、64bit に限らずオブジェクト参照の読み書きは常に atomic である
    • ただし、メモリ可視性が保障されないので非 volatile 変数ではスレッドセーフは保障されない

感想

数年越しの勘違いを正すことができた。調べて良かった。