LoggingWidget クラスのメソッド doSomething が Widget のロックを取得する必要があるのはなぜですか?
2 つのスレッドがLoggingWidget#doSomething()
同時に実行できないことを確認したい場合 (この例では、print ステートメントと への呼び出しの間でオブジェクトが変更されていないことを確認したい場合がありますsuper.doSomething()
)、メソッドを同期させる必要があります。 .
そうしないと、スレッド (T1) が実行を開始しLoggingWidget#doSomething()
てオブジェクトを出力し、別のスレッド (T2) も実行を開始しLoggingWidget#doSomething()
て (メソッドは同期されません)、オブジェクトを再度出力し、次に T2 がどちらを実行するsuper.doSomething()
か (たとえば、 ) がオブジェクトを変更し、次に T1 が実行super.doSomething()
されますが、T2 がその間に変更を加えたため、オブジェクトの状態は出力されたものとは異なります。
これを防ぐ 1 つの方法は、メソッドを同期化することです。
Widget と LoggingWidget の doSomething メソッドは両方とも同期されているため、先に進む前にそれぞれが Widget のロックを取得しようとします。
再入可能とは、特定のスレッドが既に保持しているロックを再取得できることを意味します。この場合、スレッドが に入ると、メソッドが同期されているためLoggingWidget#doSomething()
取得します。this
を実行super.doSomething()
すると、同じロックを再取得する必要があります。本質的なロックは再入可能ではなく、スレッドはそこで永久にブロックされ、すでに保持していて解放されないロックを取得しようとします = デッドロック。