synchronized、volatileキーワード

Javaにおけるマルチスレッドと並行処理の文脈で登場するsynchronizedおよびvolatileキーワードは、スレッド間の同期とメモリの可視性を制御するために使用されます。以下にそれぞれのキーワードについて詳しく説明します。


1. synchronized キーワード

synchronizedは、同時に複数のスレッドが同じコードブロックやオブジェクトにアクセスするのを防ぐためのキーワードです。これにより、**排他制御(ミューテックス)**が実現され、**クリティカルセクション(共有資源へのアクセス部分)**においてデータの一貫性が保証されます。

使用例

java
public class Counter { private int count = 0; public synchronized void increment() { count++; } public synchronized int getCount() { return count; } }

解説

  • 上記の例では、incrementgetCountsynchronizedで保護されています。

  • 複数のスレッドが同時にincrement()を呼び出しても、同時に1スレッドしかメソッドに入れないため、countの不整合が防がれます。

synchronizedの種類

  • インスタンスメソッドに付ける:そのインスタンスのロックを取得。

  • 静的メソッドに付ける:クラス自体のロックを取得。

  • コードブロックに付ける:任意のオブジェクトをロック対象にできる。

java
synchronized(this) { // このオブジェクトに対してロック }

2. volatile キーワード

volatileは、変数の可視性を保証するためのキーワードです。これは、1つのスレッドで更新された変数の値が、他のスレッドにも即座に見えるようにするために使います。

使用例

java
public class SharedData { private volatile boolean running = true; public void stop() { running = false; } public void runLoop() { while (running) { // 処理を継続 } } }

解説

  • 通常の変数では、JVMの最適化やCPUキャッシュの影響で、変更が他のスレッドにすぐには伝わらないことがあります。

  • volatileを使うことで、変数の読み書きが主記憶に直接行われるようになり、キャッシュの一貫性の問題を回避できます。

注意点

  • volatile排他制御は行わないため、インクリメント(count++のような操作)などの複数ステップを伴う操作には適さない

  • スレッドセーフな読み書きのみが対象(非アトミック操作にはsynchronizedが必要)。


synchronizedvolatileの比較

項目 synchronized volatile
主な目的 排他制御、同期 可視性の確保
アトミック操作 保証される 保証されない
性能 コストが高い(ロックの取得) 軽量だが限定的
適用対象 メソッドやコードブロック 変数(フィールド)のみ
排他制御 可能 不可

まとめ

  • synchronized排他制御に用いられ、同時アクセスによるデータの破壊を防止します。

  • volatile可視性の問題を解決する軽量な手段ですが、複雑な同期処理には不向きです。

  • 両者は目的が異なるため、場面に応じて適切に使い分ける必要があります

生成日:2025/05/03