volatile修飾子とは(修飾子とは)
メタモデルクラスでvoratile修飾子に出会いました。
そもそも修飾子とは
修飾子とは、クラスやメソッドやフィールドで最初にくっついている
public, static, private, finalとかのことです。
修飾子をくっつけることで、クラスやメソッドやフィールドの
使い方を指定したり制限したりできます。
アクセス修飾子と非アクセス修飾子の2つがある
使い方を指定したり制限したりする修飾子には、
アクセス修飾子・非アクセス修飾子の2種類があります。
アクセス修飾子
クラス・メソッド・フィールドなどのアクセス可能範囲を示します
非アクセス修飾子
クラス・メソッド・フィールドなどの使用条件を示します
アクセス修飾子
アクセス修飾子は、その名のとおり
アクセス可能範囲(どこからアクセスできるか)を示す修飾子です。
具体的には以下の4つになります。
public
public修飾子のアクセスレベルはどこにでもあります。クラス内、クラス外、パッケージ内、パッケージ外からアクセスできます。
protected
保護された修飾子のアクセスレベルは、子クラスを通じてパッケージ内およびパッケージ外にあります。子クラスを作成しないと、パッケージの外部からアクセスできません。
default
デフォルト修飾子のアクセスレベルは、パッケージ内のみです。パッケージの外部からはアクセスできません。アクセスレベルを指定しない場合は、それがデフォルトになります。
private
プライベート修飾子のアクセスレベルは、クラス内のみです。クラス外からはアクセスできません。
(引用:【Java】アクセス修飾子と非アクセス修飾子を解説します!)
アクセス可能範囲っていうのは例えば、
「どこでも使える」とか、「このクラスでしか使えない」とかの制限をつけます。
例えば、private修飾子だったら、
メソッドにprivate修飾子をくっつけることで、他クラスでそのメソッドを使えないように制限できます。
逆に、privateとつけないとどのクラスからも使えてしまいます。
private修飾子をくっつけることで、
「このメソッドにアクセスできるのは自クラスからだけ」と指定できます。
非アクセス修飾子
非アクセス修飾子は、アクセス修飾子とちがって
使用条件についての情報を示します。
使用条件っていうのは例えば、
「変更(再代入)できない」とか、「継承して使う」とかの条件をつけます。
例えば、final修飾子だったら、
フィールドにfinal修飾子をくっつけることで、変更(値の再代入)はできないようになります。
逆にfinalをつけないと、いつでも変更(値の再代入)できてしまいます。
final修飾子をくっつけることで、
「このフィールドは変更できない」と指定できます。
volatileの意味
volatileという英単語には、変わりやすいという意味があります。
volatileの付け方
volatile修飾子は、フィールドのみに使えます。
フィールドの前にくっつけてください。
他の修飾子と一緒に使いたいけど、どういう順番なの?となったら
以下の順番を参考にしてみてください。
openJDK指定の順番
- アクセス修飾子(publicかprivateかprotected)
- abstract
- static
- final
- transient
- volatile
- default
- synchronized
- native
- strictfp
(参照:Java Style Guidelines (Draft, v6))
つけるとどうなる
そもそもの話で、よく使う変数とかがあると、キャッシュメモリに保存して、そこから変数を取り出したりするんですが、
volatile修飾子をつけることで、「キャッシュメモリは使わない」という使用条件が付与されるみたいです。
つまり、毎回メインメモリから読み込むし、
変更があった場合もメインメモリに書き込むようになります。
どういうときにつける
マルチスレッドで処理を行う場合につけるっぽいです。
マルチスレッド処理を行うということは、スレッドの数だけキャッシュが使われる可能性があります。
複数のキャッシュ = 複製(コピー)されたフィールド が存在します。
もし複数のキャッシュ内でフィールドに変更がかかりまくったとしたら...
例えばキャッシュメモリA上の複製フィールドに行われた変更が、
メインメモリのフィールドに反映されても、別のキャッシュメモリBの複製フィールドでは感知できてなくて、
本来使うべきフィールドの値が使えてなかった、なんて可能性が出てきます。
そうならないように、volatile修飾子=メインメモリのフィールドにしか読み書きしないという条件をつけるみたいです。
(この例がわかりやすかったです → Javaのvolatile修飾子の使い方を現役エンジニアが解説【初心者向け】)
でも、全然見たことや使ったことはありません。
JPAのmetamodelクラスでしか見たことないです。
まとめ
volatileは「変わりやすい」という意味がありましたが、
値が変わりやすいから、メインメモリのフィールドにしか読み書きしないという条件指定をするための修飾子でした。
Discussion