synchronizedブロックとwaitに関する仮説
JavaGoldの資格勉強してて、 「なんでsynchronizedブロックでしかwait/notify/notifyAll使えないんだろう?」 と疑問に思ったので考えてみた。
間違ってるとは思うのでツッコミ待ち。
メソッド名から考えてみる
まず、Threadを一時中止するメソッドとして
java.lang.Thread.sleep
がある。 上記のクラス、メソッド名で考えると「Treadが眠る」となる。
一方、
java.lang.Object#wait
こちらは、「オブジェクトが待つ」。 何を待つか。おそらく状態の変化だ。
つまり、いずれも自身へのCPU割当を解除し、他Treadへ移譲するように JVMに指示するメソッドではあるが、 目的語があるかどうか、すなわち他と関連するかどうか、という点で異なっている。
synchronized
synchronized
は「オブジェクトにロックをかける」修飾子。
リソースにロックをかけて処理の原子性とリソースの完全性を担保する。
逆に言うと、synchronizedブロック外は(マルチスレッド環境においては)
いつ何時他のThreadの処理が行われても構わない、ということになる。
組み合わせで考えてみる
synchronizedの有無とsleep/waitの組み合わせで考えてみる。
① synchronizedなしのsleep
よくあるパターン(かどうかはわからないが)。 単にちょっと待って他のTreadに何らかの処理をさせる。 他の処理の結果は、原則的に当該処理に影響が出ない。 まあinterrup()とかしたら別だけど…。
② synchronizedなしのwait
※ もちろん実際にはIllegalMonitorStateExceptionが発生する。 他の処理に何かを期待して待つ。 あるとき、自Threadが望んだ状態になる。 しかし、その後の処理を行って居る際に割り込みが発生し、望んだ状態でなくなるかもしれない。 それを防ぐには、synchronizedを使うしかない…。
③ synchronizedありのsleep
対象リソースはロックされているので、それが変更されることはないが 一時的に自身の処理を止めることは出来る。
④ synchronizedありのwait
自身が望む状態を他のTreadに作り出してほしい。 なので、ロック対象のオブジェクトを変更する許可を出す。
こんな感じ?