見出し画像

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は「変わりやすい」という意味がありましたが、
「値が変わりやすいから、メインメモリのフィールドにしか読み書きしない」という条件指定をするための修飾子でした。


この記事が気に入ったらサポートをしてみませんか?