3

次の例を考えます。 ここに画像の説明を入力

この例は「Java Concurrency in Practice」からのものです。

コメントがあります:

Widget と LoggingWidget の doSomething メソッドは両方とも同期されているため、先に進む前にそれぞれが Widget のロックを取得しようとします。

doSomethingLoggingWidget クラスのメソッドが のロックを取得する必要があるのはなぜWidgetですか? もしそうなら、synchronized上の方法doSomethingLoggingWidget役に立たないでしょう?

4

2 に答える 2

2

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()すると、同じロックを再取得する必要があります。本質的なロックは再入可能ではなく、スレッドはそこで永久にブロックされ、すでに保持していて解放されないロックを取得しようとします = デッドロック。

于 2012-08-16T11:11:07.470 に答える
0

再入可能ロックは、すでにロックされているオブジェクトのロックを再取得することで重複を回避します。ここで重要なことは、ロックを解除してもすべてのロックが解除されるわけではないということです。JVM は、オブジェクトでロックが取得されるたびにインクリメントされ、ロックが解放されるたびにデクリメントされるカウンターを内部的に維持します。したがって、このメカニズムはデッドロックを回避するだけでなく、カウントを維持することで正確性を維持します。

于 2012-08-16T11:29:12.703 に答える