8

好奇心から、Java が wait() および notify() メソッドを実装するとき、それらは本当にロックを使用しているだけなのでしょうか? つまり、wait() はミューテックスを取得し、notify() はミューテックスを解放し、notifyAll() はすべてのミューテックスを (もちろん同じオブジェクト内で) 解放しますか?

ロックを使用するよりかさばらない以外に、wait() と notify() を使用する利点はありますか?

[編集] ブライアンのコメントの後、自分が何について混乱しているのかに気づきました。

wait はロックしません。ロックを解放し、ミューテックスの同期ステートメントを待機している他の誰かにそれを渡します。次に、ロックを持っている他の誰かから通知されるのを待ち、notify を呼び出し、ロックを元のステートメントに戻します。待機を呼び出したスレッド。そこがあなたが混乱しているところだと思います。– ブライアン 17 分前

4

5 に答える 5

13

他の質問は、言語が何を言っているかに焦点を当てていwaitますnotifyが、それはあなたの質問の内容ではないようです...実装の詳細であり、したがってJVM固有のミューテックスについて話します。

そのため、JVM を選択する必要があります。openjdk (ソースはこちらから入手可能) を選択しましょう。これらすべてを (最終的に) 処理するコードは、hotspot/src/share/vm/runtime/objectMonitor.cpp.

これは、待機セットとエントリ セットの 2 つのデータ構造を維持します。待機中のスレッドは待機セットに追加されてパークされますが、モニターを取得しようとするスレッドはエントリ セットに追加されてからパークされます。スレッドnotifyでは、待機セットから取得され、エントリ セットに追加されます。スレッドがロックを解除すると、エントリ セットがある場合はスレッドをアンパークします。これらのセットは実際にはキュー (リンクされたリスト) として実装されるため、FIFO ベースで処理されることに注意してください。

したがって、この特定のケースでは、実装は、オブジェクトのモニターを待機することと、オブジェクトのモニターを取得しようとすることを同様の方法で扱います。

しかし、これは 1 つの JVM の 1 つの実装にすぎません (他の人も同様のことをしている可能性がありますが)。したがって、これに依存することはできません。では、なぜ知りたいのかという質問だと思います。それがただの好奇心である場合は、openjdk コードを調べてください。魅力的です。この情報をコードで使用する予定がある場合は、使用しないでください。

アップデート

「公園」と言ってもあまり意味がないことに気づきました。PlatformEventスレッドをパークするコードはプラットフォーム固有です (そして、ParkEvent拡張する というオブジェクトに実装されます)。私が見ているopenjdkのバージョンでは、Linux用のパークコードはで見つけることができhotspot/src/os/linux/vm/os_linux.cpp、これは呼び出しpthread_mutex_lock(_mutex)ます...あなたの質問への答えとして、はい呼び出し待機は私のマシンでミューテックスを取るかもしれません。これよりも多くのことが起こり、この点に到達するのを妨げる可能性があることに注意してください.

于 2013-06-27T07:53:10.623 に答える
1

好奇心から、Java が wait() および notify() メソッドを実装するとき、それらは本当にロックを使用しているだけなのでしょうか? つまり、wait() はミューテックスを取得し、notify() はミューテックスを解放し、notifyAll() はすべてのミューテックスを解放しますか?

申し訳ありませんが、どれも正しくありません。:)

  • を取得するsynchronizedキーワードですmonitor。つまり、これは一種のロックです。注意: usingjava.util.concurrent.locks.Lockも同様のことを行います。
  • wait()notify()別のスレッドがメソッドまたはnotifyAll()このオブジェクトのメソッドを呼び出すか、指定された時間が経過するまで、現在のスレッドを待機させます。ロックとは関係ありません - ただし、現在のスレッドの現在のスレッドがこのオブジェクトのモニターを (synchronizedブロック/メソッド内で)既に所有している場合にのみ、このメソッドを呼び出すことができます
  • notify()このオブジェクトのモニターで待機している単一のスレッドを起動します。繰り返しますが、ロックとは関係ありませんが、現在のスレッドの現在のスレッドがこのオブジェクトのモニターを (synchronizedブロック/メソッドで)既に所有している場合にのみ、このメソッドを呼び出すことができます。
于 2013-06-23T03:39:25.373 に答える