Frage

Jemand bei der Arbeit nur die Begründung gebeten, hinter mit einer Wartezeit innerhalb eines synchronisierten wickeln.

Ehrlich gesagt kann ich die Argumentation nicht. Ich verstehe, was der javadocs sagen -, dass der Faden den Besitzer des Objekts Monitor sein muss, aber warum? Welche Probleme hat es zu verhindern? (Und wenn es tatsächlich notwendig, warum kann nicht das Warten Methode bekommen Sie den Monitor selbst?)

Ich suche nach einem ziemlich in der Tiefe, warum oder vielleicht einen Verweis auf einen Artikel. Ich konnte nicht ein in einer schnellen Google finden.

Oh, auch, wie funktioniert Thread.Sleep vergleichen?

edit: Große Menge von Antworten - ich wünsche, ich könnte mehr als eine wählen, weil sie alle halfen mir zu verstehen, was los war

.
War es hilfreich?

Lösung

Wenn das Objekt nicht das Objekt Monitor nicht besitzt, wenn er ruft Object.wait (), wird es nicht möglich sein, das Objekt zu Setup für den Zugriff auf einen Listener benachrichtigen, bis der der Monitor freigegeben wird. Stattdessen wird es als Thread behandelt Versuch auf einem synchronisierten Ziel, ein Verfahren für den Zugriff.

Oder um es anders auszudrücken, es gibt keinen Unterschied zwischen:

public void doStuffOnThisObject()

und die folgende Methode:

public void wait()

werden Beiden Methoden blockiert werden, bis das Objekt Monitor freigegeben wird. Dies ist ein Merkmal in Java, die den Zustand eines Objekts zu verhindern, dass von mehr als einem Thread aktualisiert werden. Es hat einfach unbeabsichtigte Auswirkungen auf die Methode wait ().

Vermutlich wird die Methode wait () nicht synchronisiert, weil die Situationen schaffen könnte, wo der Thread mehrere Sperren auf dem Objekt hat. (Siehe Programmiersprache Java-Spezifikationen / Sperren weitere Informationen zu diesem Thema.) mehrere Schlösser sind ein Problem, weil die Wartezeit () -Methode nur eine Sperre rückgängig gemacht wird. Wenn die Methode synchronisiert wurden, wäre es sicher, dass nur die Schlösser Verfahren rückgängig gemacht werden würden, während immer noch eine potentielle äußeree Sperre rückgängig gemacht zu verlassen. Dies würde eine Deadlock-Bedingung im Code erstellen.

Ihre Frage auf Thread.sleep zu beantworten (), Thread.sleep () garantiert nicht, dass das, was Bedingung, die Sie warten auf erfüllt ist. Mit Object.wait () und Object.notify () erlaubt es einem Programmierer manuell implementieren zu blockieren. Die Fäden werden entsperren einmal benachrichtigen gesendet wird, dass eine Bedingung erfüllt ist. z.B. Ein Lese von der Platte beendet ist und die Daten können durch den Thread verarbeitet werden. Thread.sleep () würde die Programmierer benötigen, um abzufragen, ob die Bedingung, dann fallen wieder in den Schlaf erfüllt ist, wenn es nicht hat.

Andere Tipps

Es gibt viele gute Antworten hier schon. Aber nur erwähnen möchte hier, dass die andere Muss, wenn Wartezeit mit () ist es in einer Schleife unter der Bedingung abhängig zu machen für Sie warten, wenn Sie falsche Wakeups sehen, was in meiner Erfahrung geschehen tun.

Um einen anderen Thread warten, um eine Bedingung true zu ändern und benachrichtigen:

synchronized(o) {
  while(! checkCondition()) {
    o.wait();
  }
}

Natürlich, in diesen Tagen, würde ich empfehlen, nur die neue Bedingung-Objekt, wie es klarer und verfügt über mehr Features (wie so dass mehrere Bedingungen pro Schloss, in der Lage zu sein Warteschlange Länge zu überprüfen, flexibleren Zeitplan / unterbrechen, usw. ).

 Lock lock = new ReentrantLock();
 Condition condition = lock.newCondition();
 lock.lock();
 try {
   while (! checkCondition()) {
     condition.await();
   }
 } finally {
   lock.unlock();
 }

}

Es muss den Monitor besitzen, da der Zweck der wait (), um den Monitor zu lösen ist und lassen Sie andere Threads den Monitor erhalten Verarbeitung ihrer eigenen zu tun. Der Zweck dieser Verfahren (Warte / notify) ist der Zugang zu synchronisierten Codeblöcken zwischen zwei Threads zu koordinieren, die sie erfordern einige Funktionen auszuführen. Es ist nicht einfach eine Frage der sicherstellen, dass Zugriff auf eine Datenstruktur THREAD, aber die Ereignisse zwischen mehreren Threads zu koordinieren.

Ein klassisches Beispiel wäre ein Erzeuger / Verbraucher Fall sein, wenn ein Thread Daten in eine Warteschlange schiebt, und ein anderer Thread verbraucht die Daten. Der raubend Thread würde erfordern immer den Monitor in die Warteschlange zuzugreifen, würde aber den Monitor freigeben, sobald die Warteschlange leer ist. Der Produzent Thread würde dann bekommen nur Zugriff auf den Thread zu schreiben, wenn die Verbraucher nicht mehr verarbeitet werden. Es würde die Verbraucher Thread benachrichtigen, sobald es mehr Daten in die Warteschlange geschoben hat, so kann sie den Monitor wieder und die Warteschlange zugreifen wieder.

Warten gibt den Monitor, so müssen Sie es aufgeben müssen. Benachrichtigen Sie muss auch den Monitor haben.

Der Hauptgrund, warum Sie dies tun wollen, dass Sie den Monitor, um sicherzustellen, ist, wenn Sie wieder von Warte kommen () - in der Regel, können Sie die Wartezeit verwenden / notify-Protokoll einige gemeinsam genutzte Ressource zu schützen und Sie wollen es sicher sein, es zu berühren, wenn Wartezeit zurückkehrt. Das gleiche mit benachrichtigen - in der Regel Sie etwas ändern und dann benachrichtigen () aufrufen -. Sie den Monitor haben möchten, Änderungen vornehmen und benachrichtigen nennen ()

Wenn Sie gemacht eine Funktion wie folgt aus:

public void synchWait() {
   syncronized { wait(); }
}

Sie würden nicht den Monitor, wenn Wartezurück - Sie werden es bekommen konnte, aber man kann es nicht weiter bekommen

.
scroll top