技術メモ

神奈川在住のITエンジニアの備忘録。おもにプログラミングやネットワーク技術について、学んだことを自分の中で整理するためにゆるゆると書いています。ちゃんと検証できていない部分もあるのでご参考程度となりますが、誰かのお役に立てれば幸いです。

Javaのvolatile変数

Javaの「volatile」は、「synchronized の軽量版」という認識しか持っておらず、あまり理解できていない気がしたので、ちょっと調べてみた。

マルチスレッド処理において、フィールド変数に volatile を付けると、各スレッドはその変数を参照する際、スレッド固有の領域ではなく、常に最新の値を見に行く。つまり、各スレッドが古い値を参照してしまうことはなくなる。

synchronized と何が違うのかと言うと、synchronized はロックを取得し、処理中は他のスレッドをブロックするが、volatile はそれはしない。単に、スレッドが対象のフィールド変数を参照する時に、常に最新の値を見れるようになるだけ。これをカッコよく (難しく) 言うと、volatile は「可視性」は持っているが、「アトミック性」は持っていない、ということになるとのこと。
Javaの理論と実践: volatile を扱う

なので、複数スレッドからアクセスされるクラスにおいて、例えば以下のように、あるフィールド変数の値を加算して、加算した結果が特定の数値だったら特別な処理を行いたい場合、synchronized だと実現できるが、volatile では実現できない。

volatile int counter = 0;

void updateCounter {
    counter++;
    if (counter == 100) { // ★
        doSomething();
    }
}

というのは、あるスレッドが counter を加算して counter が 100 になって ★ の箇所に入ろうとしたところに、別スレッドが counter を加算して counter が 101 になってしまう可能性があるからである。そうなると、本来実行したかった doSomething() が実行されない。

こんな感じで volatile は扱うのがちょっと難しいので、基本は synchronized を使い、それだと性能が出ない場合などに volatile を検討するくらいで良いのではないかと考えている。ちなみに、volatile の使いどころについては、以下のページが分かりやすい。
https://relearn-java.com/multithread/#title-how-to-use-volatile
上記によると、volatile の出番はあまりなさそうに思える。