20

すべての JavaObjectにはメソッドwait()and notify()(および追加のバリアント) があります。私はこれらを使用したことがなく、他の多くの人が使用していないと思います. なぜこれらは非常に基本的なものであり、すべてのオブジェクトがそれらを持たなければならず、それらを持つことでパフォーマンスが低下するのですか (おそらく何らかの状態がそれらに保存されます)。

編集して質問を強調します。100,000 個の要素を持つ がある場合、から拡張されるためList<Double>、すべてにこれらのメソッドがあります。しかし、これらすべてが.DoubleObjectList

優れた有用な回答を編集します。@Jon には、私の直感を具体化した非常に優れたブログ投稿があります。また、心配する前にパフォーマンスの問題を示す必要があるという@Bob_Crossにも完全に同意します。(また、成功した言語の n 番目の法則として、それがパフォーマンス ヒットだった場合、Sun または誰かがそれを修正したでしょう)。

4

4 に答える 4

34

まあ、それはすべてのオブジェクトが潜在的にそれに関連付けられたモニターを持たなければならないことを意味します. に同じモニターが使用されsynchronizedます。どのオブジェクトでも同期できるという決定に同意する場合は、オブジェクトごとの状態をこれ以上追加wait()notify()ないでください。JVM は実際のモニターを遅延して割り当てる場合があります (.NET がそうであることは知っています) が、どのモニターがオブジェクトに関連付けられているかを示すために、利用可能なストレージ スペースが必要です。確かに、これは非常に少量 (たとえば 3 バイト) である可能性がありますが、残りのオブジェクト オーバーヘッドがパディングされるため、実際にはメモリを節約することはできません。確かに。

追加のメソッドを使用してもパフォーマンスに影響しないことに注意してください (明らかにコードがどこかに存在するため、ごくわずかです)。wait()各オブジェクトや各タイプにとのコードの独自のコピーがあるわけではありませんnotify()。vtables がどのように機能するかによって、各型継承されたメソッドごとに追加の vtable エントリになる場合がありますが、それはオブジェクトごとではなく、型ごとにのみです。それは基本的に、実際のオブジェクト自体のためのストレージの大部分と比較して、ノイズの中で失われます.

個人的には、.NET と Java の両方が、すべてのオブジェクトにモニターを関連付けることで間違いを犯したと感じています。代わりに、明示的な同期オブジェクトを使用したいと思います。これについては、 java.lang.Object/System.Object の再設計に関するブログ投稿でもう少し詳しく説明しました。

于 2009-10-30T08:13:37.003 に答える
12

なぜこれらは非常に基本的なものであり、すべてのオブジェクトがそれらを持たなければならず、それらを持つことでパフォーマンスが低下するのですか (おそらく何らかの状態がそれらに保存されます)。

tl;dr: これらはスレッド セーフなメソッドであり、その値に比べてコストが小さくなります。

これらの方法がサポートする基本的な現実は次のとおりです。

  1. Java は常にマルチスレッドです。例: jconsole または jvisualvm を使用して、プロセスによって使用されるスレッドのリストを確認します。
  2. 正確さは「パフォーマンス」よりも重要です。私がプロジェクトの採点をしていたとき (何年も前)、「間違った答えにすぐにたどり着くのはまだ間違っている」と説明しなければなりませんでした。

基本的に、これらのメソッドは、同期で使用されるオブジェクトごとのモニターを管理するためのいくつかのフックを提供します。具体的にはsynchronized(objectWithMonitor)、特定のメソッドを持っている場合objectWithMonitor.wait()、そのモニターを生成するために使用できます (たとえば、先に進む前に計算を完了するために別のメソッドが必要な場合)。その場合、ブロックされていた別の 1 つのメソッドが、そのモニターの進行を待機できるようになります。

一方、objectWithMonitor.notifyAll()モニターを待機しているスレッドに、モニターをすぐに放棄することを知らせるために使用できます。ただし、同期ブロックを離れるまで、実際には先に進むことはできません。

モニタリング メカニズムでパフォーマンスやメモリ ヒットが発生する可能性がある特定の例 (たとえば、長い double のリスト) に関して、考慮すべき点がいくつかあります。

  1. まず、それを証明してください。マルチスレッドの正確性など、Java のコア メカニズムに大きな影響があると考える場合、その直感が間違っている可能性は十分にあります。最初に影響を測定します。それが深刻で、個々の Double で同期する必要がないことがわかっている場合は、代わりに double を使用することを検討してください。
  2. あなた、あなたの同僚、将来のメンテナンス コーダー (1 年後のあなた自身かもしれません) などが、あなたのデータへの細かい粒度のスレッド化されたアクセスを決して必要しないかどうか確信が持てない場合は、その可能性が非常に高くなります。これらのモニターを取り除くと、コードの柔軟性と保守性が低下するだけです。

オブジェクトごとと明示的な監視オブジェクトに関する質問に対するフォローアップ:

簡単な回答: @JonSkeet: はい、モニターを削除すると問題が発生します。摩擦が発生します。これらのモニターを維持すると、これが常にマルチスレッド システムObjectであることを思い出させてくれます。

組み込みのオブジェクト モニターは洗練されたものではありませんが、次の点に優れています。予測可能な方法で作業します。そしてその目的は明確です。 synchronized(this)明確な意思表示です。初心者のコーダーに同時実行パッケージのみを使用するように強制すると、摩擦が発生します。そのパッケージには何が入っていますか?セマフォとは?フォークジョイン?

初心者のコーダーは、オブジェクト モニターを使用して適切なモデル ビュー コントローラー コードを作成できます。 synchronizedwaitあり、notifyAll素朴な (シンプルでアクセスしやすいが、おそらく最先端のパフォーマンスではないという意味で) スレッドセーフを実装するために使用できます。標準的な例は、AWTスレッドが値を取得してJLabelに配置する間に、1つのスレッドに値を設定させることができるこれらのDoubleの1つです(OPによって提示されます)。その場合、外部モニターを持つためだけに明示的な追加オブジェクトを作成する正当な理由はありません。

やや複雑なレベルでは、これらの同じ方法が外部監視方法として役立ちます。上記の例では、明示的にそれを行いました (上記の objectWithMonitor フラグメントを参照)。繰り返しになりますが、これらのメソッドは、比較的単純なスレッド セーフをまとめるのに非常に便利です。

さらに高度になりたい場合は、 Java Concurrency In Practiceを読むことを真剣に検討する必要があると思います(まだ読んでいない場合)。読み取りロックと書き込みロックは非常に強力であり、複雑さを増しすぎることはありません。

パンチライン:基本的な同期方法を使用すると、スレッド セーフを備えた最新のマルチコア プロセッサによって実現されるパフォーマンスの大部分を、多くのオーバーヘッドなしで活用できます。

于 2009-10-30T08:58:45.463 に答える
2

Java のすべてのオブジェクトには、モニターが関連付けられています。同期プリミティブは、ほぼすべてのマルチスレッド コードで役立ちます。意味的には、個別の「監視」オブジェクトではなく、アクセスしているオブジェクトで同期するのが非常に便利です。

Java は、オブジェクトに関連付けられたモニターを必要に応じて割り当てることができます (.NET と同様)。いずれにせよ、単にロックを割り当てる (ただし使用しない) ための実際のオーバーヘッドは非常に小さくなります。

要するに、スレッド セーフ サポート ビットを使用してオブジェクトを格納するのは非常に便利であり、パフォーマンスへの影響はほとんどありません。

于 2009-10-30T08:16:38.683 に答える
1

これらのメソッドは、スレッド間通信を実装するために存在します。

件名のこの記事を確認してください。

その記事から抜粋したこれらのメソッドのルール:

  • wait( ) は、呼び出し元のスレッドに、モニターを放棄して、他のスレッドが同じモニターに入り、notify( ) を呼び出すまでスリープ状態になるように指示します。
  • notify( ) は、同じオブジェクトで wait( ) を呼び出した最初のスレッドを起動します。
  • notifyAll( ) は、同じオブジェクトで wait( ) を呼び出したすべてのスレッドを起動します。最も優先度の高いスレッドが最初に実行されます。

お役に立てれば...

于 2009-10-30T08:12:17.210 に答える