すべてのJavaオブジェクトにwait()とnotify()があるのに、パフォーマンスが低下するのはなぜですか?

StackOverflow https://stackoverflow.com/questions/1648551

  •  22-07-2019
  •  | 
  •  

質問

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

編集して質問を強調します。 100,000個の要素を持つList<Double>がある場合、Doubleから拡張されるため、すべてのListにはこれらのメソッドがあります。しかし、これらすべてが<=>を管理するスレッドについて知る必要があるとは考えにくいようです。

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

役に立ちましたか?

解決

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

余分なメソッドを追加するだけでは、パフォーマンスには影響しません(コードがどこかに存在することはごくわずかですが)。それは、各オブジェクトや、各タイプが<=>と<=>のコードの独自のコピーを持っているようなものではありません。 vtableの動作方法によっては、各タイプは、継承されたメソッドごとに 余分なvtableエントリになる場合がありますが、それはオブジェクトごとではなくタイプごとにのみ行われます。基本的には、実際のオブジェクト自体のストレージの大部分と比較して、ノイズで失われます。

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

他のヒント

  

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

tl; dr:これらはスレッドセーフなメソッドであり、値に比べてコストはわずかです。

これらのメソッドのサポートは次のとおりです:

  1. Javaは常にマルチスレッドです。例:jconsoleまたはjvisualvmを使用して、プロセスで使用されるスレッドのリストをしばらく確認します。
  2. 正しさは<!> quot; performance。<!> quot;よりも重要です。 (数年前)プロジェクトを採点していたとき、<!> quot;間違った答えにたどり着くのは本当に速いでもまだ間違っていた。<!> quot;

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

一方、objectWithMonitor.notifyAll()を使用して、モニターを待っているスレッドに、すぐにモニターを放棄することを知らせることができます。ただし、同期ブロックを終了するまで、実際には続行できません。

監視メカニズムでパフォーマンスまたはメモリヒットが発生するのではないかと心配する可能性のある特定の例(たとえば、Doubleの長いリスト)については、次の点を考慮する必要があります。

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

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

簡単な答え: @JonSkeet:はい、モニターを削除すると問題が発生し、摩擦が発生します。これらのモニターをObjectに保持すると、これは常に常にマルチスレッドシステムであることがわかります。

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

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

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

yの場合もっと洗練したいので、 Java同時実行の実践(あなたはまだ持っていません)。読み取りロックと書き込みロックは、複雑さをあまり追加することなく非常に強力です。

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

Javaのすべてのオブジェクトには、モニターが関連付けられています。同期プリミティブは、ほとんどすべてのマルチスレッドコードで有用であり、セマンティック上、個別の<!> quot; Monitor <!> quot;ではなく、アクセスしているオブジェクトで同期するのに非常に便利です。オブジェクト。

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

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

これらのメソッドは、スレッド間通信を実装するためのものです。

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

それらのメソッドのルール、その記事から引用:

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

これが役立つことを願っています...

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top