2016-02-16 6 views
12

wait,notifyおよびnotifyAllのメソッドはObjectに配置されていますが、いくつかの分離クラスではありません。なぜwait()とnotify()が特別なクラスに含まれていないのですか?

この質問は、Threadクラスに移動することについてではありません。私はなぜ彼らがObjectを捨てているのか疑問に思っています。新しいMonitorクラスではありません。

私はそのアイデアの以下の欠点を参照してください。

  • 私たちは、モニターとして私たちのために、他の目的のフィールドを使用することはできません。しかし、これはモジュール性の原則に合っているようです。
  • this<MyClass>.classが有効なモニターにならないように、同期されたメソッドは、(クロージャのように)生成された隠しフィールドでいくつかのハックを必要とするようになりました。

私たちは少しの悲惨さですべてのオブジェクトから5つの方法を外すことができました。か否か?

+0

「なぜ彼らはオブジェクトが新しいMonitorクラスではないのだろうか」と考えています。概念的には内部的に行いますが、モニターはオブジェクトごとに一意です。重複した回答を参照してください(たとえ 'Thread'を参照していますが) –

+1

@biziclopまさに。 Per Brinch HansenがJavaの初期並行性構成を見たとき、彼は「明らかに私は無駄に努力しました」と書いています。彼らはUNIXの驚くべき 'sleep/wakeup()'内部から借りたようです。 – EJP

+0

* "私たちは少しの悲しみですべてのオブジェクトから5つのメソッドを取り除くことができました" *技術的には、これらのメソッドは技術的に1回だけ存在し、インスタンスごとには1回しか存在しません。 – m0skit0

答えて

7

本物の答えは間違いであり、最終的にはConditionクラスの作成で認められています。これはまさにあなたが期待するものです。 抱き合わせ、すでにリストアップしました事は別に

を(それが対象ですので、あなたが誤って...陽気な結果で、await()するのではなく、それにwait()を呼び出すだろうという可能性がありますが) 1つのオブジェクトごとに監視することで、Javaで真に不変なオブジェクトを持つことが不可能になります。

だから、たとえば、これを行うことができます。

class A { 
    void foo() { 
     synchronized((Integer)42) { 
     ... 
     } 
    } 
} 

class B { 
    void foo() { 
     synchronized((Integer)42) { 
      ... 
     } 
    } 
} 

は、オブジェクトが不変だった場合、すべての時間が問題になることはありません42に同じ箱入り整数を返します。しかし、そうではありません、それは可変状態を持っています:そのような同期を可能にするモニター。これは特に悪いことですが、その面で独立しているように見える2つのコード間にミューテックスを作成したことです。

+0

注目すべき答え。例えばキャッシングを使って+1を追加したいIntegers – Martoon

+1

@Martoon練習として、私はこれを利用して互いに通信する[入出力のストリームのペア](http://pastebin.com/r2bKbXfE)を書きました。実際には恐ろしいことは、同じVMに2つのWebアプリケーション(たとえば同じコンテナ内に2つのWebアプリケーション)を置いても、どこでも動作するということです。 – biziclop

0

すべてのオブジェクトがモニタとして機能できるためです。

+0

はい、問題は別のクラスを持たない理由です。 – m0skit0

0

1)待機と通知は、通常の方法や同期ユーティリティではなく、Javaの2つのスレッド間の通信メカニズム以上です。また、Objectクラスは、synchronizedなどのjavaキーワードでこのメカニズムが利用できない場合は、すべてのオブジェクトで使用できるようにするための正しい場所です。覚えておいてください。同期して待ってください通知は2つの異なる領域であり、それらが同じか関連していることを混同しないでください。同期は、相互排除を提供し、競合状態のようなJavaクラスのスレッド安全性を保証することであり、待機と通知は2つのスレッド間の通信メカニズムです。

2)オブジェクト単位でロックが使用可能になります。これは、待機と通知がスレッドクラスではなくオブジェクトクラスで宣言されるもう1つの理由です。

3)Javaでは、コードの重要なセクションに入るために、スレッドはロックを必要とし、ロックを待つか、ロックを保持しているスレッドがわからず、ロックがあるスレッドによって保持されていることを知り、どのスレッドが同期ブロック内にあるかを知り、ロック解除を要求するのではなく、ロックを要求します。このアナロジーは、Javaのスレッドではなく、オブジェクトクラス上に待機して通知するのに適しています。REFと

http://javarevisited.blogspot.in/2012/02/why-wait-notify-and-notifyall-is.html

1

本の利点の一つは、あなたは、単にそれのために冗長なモニターを作成することなく、参照に同期させることができるということです。

synchronized (myList) { 
    myList.add(0); 
} 

private final Object mySpecialMonitor = new Object(); 

syncronized(mySpecialMonitor) { 
    myList.add(0); 
} 

対それはですすべての同期が別のクラスにある場合は機能しません。

+0

はい、それは私が挙げた最初の欠点です。しかし、そのように考えると 'ReentrantLock.lock()'、 'unlock()'、 'StringBuilder.append()'、私はそれ以外ではないと思われる 'Object'クラスいいターン。つまり、 'Object'クラスは同期化のための特殊化を意図していません – Martoon

+2

私はこれを利点と呼んでいません。安全な同期の仕方は、公開されているオブジェクト上で行うのではないので、大抵の場合、プライベートファイナルのフィールドに専用のロックオブジェクトを作成することになります。 – biziclop