wake-up-neo.com

synchronisiertes Objekt auf null gesetzt

Ich habe zwei Threads Thread1 und Thread2

//Within Thread1     
synchronized(obj1)  
{  
    obj1 = null;  
}  

//Within Thread2  
synchronized(obj1)  
{  
    do something  
}   

Wenn jvm zuerst thread1 ausführt und obj1 auf null setzt, wird Thread2 diese Änderung sofort sehen oder dauert es Zeit, und jvm könnte den synchronisierten Thread2-Block noch ausführen, da obj1 noch nicht null ist.

22
vjk

Dies wird die Synchronisationsabstraktion höchstwahrscheinlich brechen - ich bin nicht zuversichtlich, dass thread2 die Änderung sofort sehen wird. Sie sollten niemals die Referenz des Objekts, auf das Sie synchronisieren, ändern, oder weniger auf null setzen, was bei weiteren Synchronisierungsversuchen eine NullPointerException verursacht.

33
Louis Wasserman

Lassen Sie mich zunächst betonen, dass das Ändern einer Variablen, die für die Synchronisation verwendet wird, eine schrecklich schlechte Sache ™ ist. obj1 sollte final sein und niemals berührt werden, wenn er als Monitor verwendet wird.

Zurück zu Ihrer Frage:

Wenn JVM zum ersten Mal Thread1 ausführt, wird es bei obj1 synchronisiert, auf null gesetzt und der Thread beendet. Der zweite Thread möchte auf obj1 synchronisieren, NullPointerException wird ausgelöst. Da die Änderung von obj1 im synchronisierten Block vorgenommen wurde, ist garantiert, dass Thread2 einen aktualisierten Wert erhält (also: NullPointerException ist garantiert).

Wenn Thread1 unterbrochen wird, nachdem die Sperre für obj1 erlangt wurde, jedoch vor dem Löschen der Referenz, sperrt Thread2 obj1 und wartet, bis Thread1 beendet ist. Dann wird der Monitor erfolgreich in den Monitor aufgenommen, da das zuvor von obj1 referenzierte Objekt noch vorhanden ist.

12

synchronized synchronisiert das Objekt und nicht die Referenz. Wenn Sie obj1 (eine Referenz) auf null setzen, kann Thread2 nicht mit dem Objekt synchronisiert werden, auf das zuvor mit obj1 verwiesen wurde. Stattdessen wird stattdessen eine NullPointerException angezeigt.

4
Steve Kuo

Die Änderung ist sofort wirksam. Wenn Thread 1 die Sperre "besitzt", kann er den Wert von obj1 nach Belieben ändern. Thread 2 muss warten, bis Thread 1 die Sperre freigibt. Es wird definitiv obj1 == null sehen

1
mprivat

Eine schnelle Lösung besteht darin, aus dem Objekt ein einfaches Array mit einem Element zu machen und auf das Array für die Synchronisation zu verweisen, z.

Objekt [] obj1 = {null};

Das Element kann null sein, ohne dass die Existenz des Arrays beeinträchtigt wird. Zwar verstößt dies immer noch gegen die "Regel", bei der das Objekt selbst nicht zur Synchronisation verwendet wird. Wenn Ihr Code jedoch an anderer Stelle die Dinge kompliziert, sollte diese schnelle Korrektur wie erwartet funktionieren.

1
Jerry Miller