Wait () / notify () Synchronisation

8

Ich versuche zu überprüfen, wie wait / notify in Java funktioniert.

Code:

%Vor%

Ausgabe zurückgegeben

%Vor%

Ich habe erwartet, dass wenn notify () ausgeführt wird, die Wartezeit vorbei sein wird & amp; System.out.println("wait over"); wird gedruckt. Aber es scheint, dass es nur gedruckt wird, wenn t sein run() beendet hat.

    
reiley 01.07.2013, 06:51
quelle

3 Antworten

9

Objektmonitorsperren müssen eine einzelne Referenz derselben Sperre ausführen ...

In Ihrem Beispiel sind Sie waiting für eine Instanz von Thread , aber verwenden notify von Runnable . Stattdessen sollten Sie ein einzelnes, gemeinsames Sperrobjekt verwenden ... zum Beispiel

%Vor%

Ausgabe ...

%Vor%

wait over und leaving run method können die Positionen abhängig von der Thread-Planung ändern.

Sie könnten versuchen, den Schlaf außerhalb des Blocks synchronized zu setzen. Dadurch wird die Monitorsperre aufgehoben, sodass der Abschnitt wait weiter ausgeführt werden kann (da er nicht gestartet werden kann, bis die Sperre aufgehoben wird)

%Vor%     
MadProgrammer 01.07.2013, 06:53
quelle
5

Antwort auf aktualisierten Code:

Von Thread.sleep () Javadoc:

  

Bewirkt, dass der aktuell ausführende Thread in den Ruhezustand versetzt wird (Ausführung vorübergehend anhalten)   angegebenen Anzahl von Millisekunden, abhängig von der Genauigkeit und Genauigkeit der System-Timer   und Scheduler. Der Thread verliert keine Eigentumsrechte an Monitoren .

Wenn Sie Thread.sleep innerhalb eines synchronisierten Blocks aufrufen, können andere Threads den synchronisierten Block nicht betreten. Sie sollten niemals zeitraubende Aufgaben in einem synchronisierten Block ausführen, um dies zu vermeiden.

    
Pyranja 01.07.2013 07:18
quelle
1

Beachten Sie (wie auch andere darauf hingewiesen haben), dass Sie in beiden Threads dasselbe Objekt zum Sperren / Synchronisieren verwenden müssen.

Wenn Sie möchten, dass Ihr Haupt-Thread sofort fortgesetzt wird, nachdem notify aufgerufen wurde, müssen Sie die Sperre vorübergehend aufgeben. Andernfalls wird wait erst aufgerufen, nachdem der sekundäre Thread den synchronized -Block verlassen hat. Und es ist nie eine gute Idee, eine Sperre in einer lang laufenden Berechnung zu halten!

Eine Möglichkeit, wie Sie dies erreichen können, ist die Verwendung von wait(int) für die Sperre anstelle von sleep , weil wait die Synchronisierungssperre vorübergehend freigibt:

%Vor%

Allerdings kann die Verwendung dieser Low-Level-Primitive sehr fehleranfällig sein, und ich würde davon abraten, sie zu verwenden. Stattdessen würde ich Ihnen vorschlagen, die High-Level-Primitive von Java dafür zu verwenden. Zum Beispiel können Sie CountDownLatch verwenden, wodurch ein Thread warten kann, bis andere Threads auf Null zählen:

%Vor%

Hier müssen Sie nichts synchronisieren, der Riegel erledigt alles für Sie. Es gibt viele andere Grundelemente, die Sie verwenden können - Semaphore, ein Exchanger, thread-sichere Warteschlangen usw. Entdecke das java.util.concurrent -Paket.

Vielleicht ist eine noch bessere Lösung, eine noch höhere API zu verwenden, wie Akka bietet. Dort arbeiten Sie mit Schauspielern oder Softwaretransaktionsspeicher , der leicht zusammengestellt werden kann und Ihnen die meisten Nebenläufigkeitsprobleme erspart.

    
Petr Pudlák 01.07.2013 08:09
quelle