✅ wait(), notify(), notifyAll()の正しい使い方

Java

~スレッド間通信を完全に理解しよう!~

はじめに:なぜこの3つを理解すべきなのか?

Java のマルチスレッドを学ぶと、必ず出てくるのが
wait()notify()notifyAll() という3つのメソッドです。

「なんとなくスレッドを止めたり再開したりするもの」
と理解している方も多いですが、実はこの3つの使い方を誤ると
プログラムが止まる・動かない・データ破損が起きるなどの問題が発生します。

逆に、正しく理解すれば次のようなメリットがあります。

  • 並行処理を安全に扱える
  • 他の言語のスレッド制御も理解できる
  • Java の「モニター機構」の本質が分かる

特に、スレッド間通信の理解は中級者への大きなステップアップです。


基本の理解:Java のスレッドとモニター機構

Java のすべてのオブジェクトは「モニター(monitor)」というロック機構を持っています。
wait()notify()notifyAll() はこのモニターと深く関係しています。

これらは Object クラス に定義されており、すべてのオブジェクトで利用可能です。

ただし、これらは必ず synchronized ブロックの中で呼ぶ必要があります。
モニターを取得していない状態で呼び出すと、IllegalMonitorStateException が発生します。


wait() の正しい使い方

wait() は、「スレッドを一時停止してロックを解放する」ためのメソッドです。

基本形

ここでの重要ポイント:

  • if ではなく while を使う
    → 「スプリアスウェイクアップ(意図せぬ再開)」に備えるため。
  • 条件を再確認すること
    → 条件が偽のまま再開することを防ぐ。

notify() の正しい使い方

notify() は、「待機中のスレッドを1つだけ再開させる」メソッドです。

ポイント:

  • 必ず synchronized ブロック内で呼ぶ
  • 起こされるスレッドはランダム(選べない)
  • 起こされたスレッドは、ロックを再取得するまで待つ

したがって、複数スレッドが待機している場合、どれが起きるかは保証されません。


notifyAll() の正しい使い方

notifyAll() は、待機しているすべてのスレッドを再開させるメソッドです。

全スレッドが一斉に実行されるわけではなく、
ロックを再取得できたスレッドから順番に実行されます。

使い分けの目安

メソッド起こすスレッド数適用シーン
notify()1つ1対1の通信(例:1つの生産者と1つの消費者)
notifyAll()全員複数スレッドが待機している場合

よくある間違いと注意点

❌ wait() を synchronized 外で呼ぶ

✅ 正しくはこう


❌ if を使って条件判定する

✅ while で条件を再確認


❌ 状態を変えずに notify() する

状態を更新してから notify() を呼ばないと、
起こされたスレッドがすぐまた待機に戻ってしまいます。


実践例:プロデューサー・コンシューマー問題

このコードは典型的な「生産者・消費者問題」を解決しています。

  • 生産者 → 満杯なら wait()
  • 消費者 → 空なら wait()
  • どちらかが動くたびに notifyAll() で相手を起こす

シンプルながら、これがスレッド間通信の本質です。


代替手段との比較

最近では、より安全で使いやすい仕組みが java.util.concurrent に用意されています。

  • ReentrantLockCondition
  • BlockingQueue
  • Semaphore
  • CountDownLatch

これらを使うと、バグを減らしつつ効率的なスレッド制御が可能です。
ただし、wait/notify の仕組みを理解していないと、これらの本質は理解できません。


まとめ

  • wait() はスレッドを待機させ、ロックを解放する
  • notify() は1つのスレッドを再開させる
  • notifyAll() は全スレッドを再開させる
  • すべて synchronized 内で呼ぶ必要がある
  • 条件確認は while を使う
  • 状態を更新してから通知する

これらを正しく理解できれば、マルチスレッドはもう怖くありません。


Javaプログラマーを目指すあなたへ

スレッド制御は、Java学習の中でも難関の一つです。
理解できたつもりでも、実際にコードを書くと「なぜ動かない?」と悩む方は多いです。

そんなときは、まず 絶対にJavaプログラマーになりたい人へ。 を読んでみてください。
この書籍は、Javaの基本から実践まで体系的に理解できるよう構成されています。

そして、
「コードレビューをしてもらいたい」
「転職を見据えて実践的なスキルを学びたい」
という方は、サイゼントアカデミー がおすすめです。

絶対にJava で学んだ基礎を、サイゼントアカデミー で実践に変える。
この2ステップで、あなたも確実に「現場で通用するJavaプログラマー」になれます。


これが、
「wait(), notify(), notifyAll()」を正しく理解するための完全ガイドです。
あなたのJavaスキルが、ここから一段上のレベルへ進むことを願っています。

コメント

タイトルとURLをコピーしました