28

私には2つのスレッドがThread1あり、Thread2

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

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

jvm が最初に thread1 を実行し、obj1 を null に設定した場合、thread2 はその変更をすぐに確認しますか、それとも時間がかかりますが、obj1 がまだ null ではないため、jvm は引き続き thread2 の同期ブロックを実行できますか?

4

5 に答える 5

41

これにより、ほぼ確実に同期の抽象化が破らthread2れます。変更がすぐに反映されるかどうかはわかりません。同期しているオブジェクトの参照は絶対に変更しないでnullくださいNullPointerException

于 2012-04-17T16:20:06.973 に答える
15

最初に、同期に使用される変数を変更することは非常に悪いことであることを強調しておきます。モニターとして使用する場合は絶対に触らないでobj1ください。final

そうは言っても、あなたの質問に戻ります:

JVM が最初に Thread1 を実行すると、同期してobj1に設定されnull、スレッドが終了します。で同期しようとしている 2 番目のスレッドがスローされますobj1NullPointerExceptionの変更はobj1同期ブロックで行われたため、Thread2 が更新された値を参照することが保証されます (したがって、保証されますNullPointerException)。

obj1ロックオンを取得した後、参照をクリアする前にThread1 が中断された場合、Thread2 はロックオンしobj1、Thread1 が終了するまで待機します。以前に によって参照されていたオブジェクトがobj1まだ存在するため、正常にモニターに入ります。

于 2012-04-17T16:22:25.033 に答える
5

synchronized参照ではなく、オブジェクトで同期します。(参照)をnullに設定obj1すると、thread2は、以前にが指していたオブジェクトで同期できなくobj1なり、代わりに取得できますNullPointerException

于 2012-04-17T17:43:16.977 に答える
2

簡単な修正は、オブジェクトを 1 つの要素の単純な配列にし、同期のために配列を参照することです。

オブジェクト[] obj1 = {null};

要素は、配列の存在に影響を与えずに null にすることができます。確かに、これはオブジェクト自体を同期に使用しないという「ルール」に違反しますが、コードが他の場所で問題を複雑にしない限り、このクイックフィックスは期待どおりに機能するはずです。

于 2014-04-28T14:41:59.900 に答える
1

変更は即時です。スレッド 1 がロックを「所有」すると、obj1 の値を自由に変更できます。スレッド 2 は、スレッド 1 がロックを解放するまで待機する必要があります。間違いなく obj1 == null が表示されます

于 2012-04-17T17:47:39.790 に答える