【Java入門】volatileとは?サンプルコードで解説!

長野 透
書いた人 長野 透
侍エンジニア塾ブログは、未経験からWebアプリ開発と仕事獲得をサポートする
侍エンジニア塾のオウンドメディアです。
プログラミング学習を覗き見

こんにちは!フリーランスの長野です。

volatileって使ってますか?

volatileは修飾子の一つで、マルチスレッド処理で使われます

この記事では、volatile修飾子について

・volatileとは
・volatileの使い方

という基本的な内容から、

・synchronizedとの違い
・Threadについて

など応用的な内容についても解説していきます。

今回はvolatile修飾子について、使い方をわかりやすく解説します!

volatileとは?

volatileはJavaの修飾子の一つで、マルチスレッド処理で使われます。

フィールドの値は通常メモリから呼び出され、更新されたりします。

ただこれはシングルスレッドの場合で、マルチスレッドの場合はこれとは違ってきます。

スレッドが一列で順番に処理されていくことを、「シングルスレッド」と言います。

これに対して、スレッドの列が2つ以上複数あり並列に同時進行で処理されていくことを「マルチスレッド」と言います。

マルチスレッド処理の場合、それぞれのスレッドが同じフィールドの値を別々にキャッシュすることがあります。

キャッシュとはメモリとは違う場所に値を保持することで、一般的にメモリに比べて保存容量は少ないですが、高速に値の呼び出しや更新ができます。

マルチスレッドの場合、フィールドの値をメモリより高速に呼び出し・更新するためにキャッシュすることがあるのです。

ここで注意しなければならないのが、それぞれのスレッドが同じフィールドの値を別々にキャッシュすると、同じフィールド名であっても値が違ってくる危険性があるということです。

次のようなwhile文を記述し、コンパイルのあとに実行する場合を考えてみましょう。

このwhile文のブロック内でflagの値を操作しない場合、while文の条件式を毎回評価する必要はありません。

このような場合にwhile文はコンパイラによって以下のように最適化することが可能になります。

シングルスレッドの場合はwhile文のブロック内でflagの値を操作しない場合、このように最適化されても問題ありません。

ただし、マルチスレッドの場合は前述のとおり他のスレッドからflagの値を操作されることがあります。

もし他のスレッドからflagの値を操作され変更された場合、最適化によってループから抜けられなくなる不具合が発生してしまうのです。

そこで、このような処理を行う場合はvolatile修飾子を使用します。

volatileの使い方

volatile修飾子の使い方をサンプルコードで確認しましょう。

実行結果:

このサンプルコードではフィールドcountの値が更新された場合に出力表示するスレッドクラスMultiThread1と約500ミリ秒ごとにcountの値を1ずつ増やすスレッドクラスMultiThread2を並列で処理しています。

MultiThread1クラスのwhile文の条件式にはフィールドcountが使われていますが、while文のブロック内ではcountの値は操作されていません。

この場合コンパイラで最適化される可能性がありますが、volatile修飾子を使って最適化を抑止しています。

以下の実行結果はvolatile修飾子なしの場合の実行結果です。

実行結果(volatile修飾子なしの場合):

このサンプルコードを実行すると、上記の実行結果を表示したあと無限にループし続けます

注意してください。

この場合volatile修飾子を使っていませんので、コンパイラで最適化され、意図した処理とは違う処理が実行されていると考えられます。

synchronizedとの違い

ここまではコンパイラの最適化の抑止について説明しました。

その他にもvolatile修飾子をフィールドにつけることで、マルチスレッド処理でメモリとキャッシュで値が違ってしまう危険性を避けるためにフィールドの値がキャッシュされるのを抑止することができます。

同じようにメモリとキャッシュで値が違ってしまう危険性を避けるためにsynchronized修飾子が使われます。

synchronized修飾子の付いたブロック内で扱うフィールドの値は、必ず元のメモリー上から呼び出し・更新されますので、キャッシュによる値の不整合を避けることができます。

volatile修飾子は簡単な値の読み書き操作で、synchronized修飾子を付けて扱うまでもない場合に使います。

synchronized修飾子ではスレッド・セーフが保証されていますが、volatile修飾子はスレッド・セーフは保証していませんので注意しましょう!

volatile修飾子とsynchronized修飾子のその他の違いについてはこちらでも詳しく解説しています。

https://www.javamex.com/tutorials/synchronization_volatile.shtml

Threadについて

マルチスレッドおよびThreadクラスについてはこちらで詳しく解説していますので、ぜひ参考にしてください。

まとめ

ここでは、volatile修飾子について説明しました。

マルチスレッド処理でフィールドの値が他のスレッドで変更される場合、コンパイルの最適化によって無限ループにならないか注意する必要があります。

マルチスレッドの記述は最初は複雑だと感じるかもしれませんが、慣れて使いこなすことができるようにこの記事を何度も参考にして下さいね!

Javaカリキュラム無料公開中!
この記事はJava入門完全攻略ガイド【基礎学習/アプリ開発/仕事獲得】の一部になります。このカリキュラムは、プログラミング入門者が、基礎学習からアプリ開発、さらには仕事獲得まで体系的に学べる内容となっています。

Java学習に必要な情報を一つにまとめていますので効率よくJavaを学ぶことが出来ます。この機会に是非活用していただければと思います。


33歳、未経験だった僕がフリーエンジニアになれた理由
現在フリーランスをされている市川友哉さん。33歳で、プログラミングを学び始め、4ヶ月という短い期間でフリーランスエンジニアとして独立までされた学習ログを余すことなくインタビューさせていただきました。

プログラミングを学習中の方はもちろん、独立をお考えの方まで幅広く活用できる記事になっています。この機会に是非活用していただければと思います。


最短でJavaを習得したい方へ

もし、あなたが、

「難しすぎて学習が全然進まない」
「学習量が膨大でゴールが見えない」
「エラーを解決するのに何日もかかってしまう」

など、プログラミング学習やキャリアに関してお困りであれば、まずは『無料体験レッスン』にお申し込み下さい。

あなたにとって、最適の解決策をご提案させていただきます。

詳しくは下の画像から詳しいサービス内容をご確認ください。

cta_bannar-java2

非常識な結果を出した卒業生

活躍する現役エンジニア

人気記事セレクション

LINEで送る
Pocket

この記事が気に入ったら
いいね!をしてフォローしよう

最新情報をお届けします

書いた人

長野 透

長野 透

熊本在住のフリープログラマ兼ライターです。C/C++/C#、Java、Python、HTML/CSS、PHPを使ってプログラミングをしています。専門は画像処理で最近は機械学習、ディープラーニングにはまっています。幅広くやってきた経験を活かしてポイントをわかりやすくお伝えしようと思います。
お問合せはこちらでも受け付けています。
[email protected]