45

再入可能とは、呼び出しごとではなく、スレッドごとにロックが取得されることを意味します。

固有のロックはスレッドが保持しているので、一度実行されたスレッドは呼び出しベースに等しいということでしょうか?

ありがとう、それは次のことを意味しているようです: スレッドで、 functionを呼び出し、さらにロックが必要な関数をlockA処理するときにロックを取得すると、再入可能になります。Javaではこの現象はスレッド単位で取得されるので、デッドロックは考慮しなくてもいいのでしょうか?doAdoBdoBlockA

4

6 に答える 6

22

次のようなものを想像してください。

function A():
   lock (X)
       B()
   unlock (X)

function B():
    A()

次に、A を呼び出します。次のことが起こります。

  • Aを入力し、Xをロックします
  • Bに入ります
  • もう一度 A を入力し、X を再びロックします

A の最初の呼び出しを終了していないため、X はまだロックされています。これは再入と呼ばれます - 関数 A がまだ戻っていない間に、関数 A が再度呼び出されます。A が何らかのグローバルな静的状態に依存している場合、これにより「再入バグ」が発生する可能性があります。静的状態が関数の終了からクリーンアップされる前に、関数が再度実行され、半分計算された値が最初の部分と衝突します。 2回目の呼び出し。

この場合、すでに保持しているロックに遭遇します。ロックが再入可能である場合、すでにロックを保持している同じスレッドであることが認識され、通過させられます。そうしないと、永久にデッドロックになります。すでに保持しているロックを待機することになります。

Java ではlocksynchronized再入可能です。ロックがスレッドによって保持されていて、スレッドが同じロックを再取得しようとすると、それが許可されます。したがって、上記の疑似コードを Java で記述した場合、デッドロックは発生しません。

于 2013-05-12T04:47:10.083 に答える
12

Java の並行性に関する実践書の状態 -Reentrancy means that locks are acquired on a per-thread rather than per-invocation basis.

それが正確に何を意味するのかを説明しましょう。まず、組み込みロックは本質的に再入可能です。再入可能性を実現する方法は、取得したロックの数とロックの所有者のカウンターを維持することです。カウントが 0 で所有者が関連付けられていない場合は、どのスレッドもロックを保持していないことを意味します。スレッドがロックを取得すると、JVM は所有者を記録し、カウンターを 1 に設定します。同じスレッドが再度ロックを取得しようとすると、カウンターがインクリメントされます。また、所有スレッドが同期ブロックを終了すると、カウンターが減分されます。カウントが再び 0 になると、ロックが解除されます。

簡単な例は次のとおりです-

public class Test {
    public synchronized void performTest() {
       //...
    }
}

public class CustomTest extends Test {
    public synchronized void performTest() {
       //...
       super.performTest();
    }
}

再入可能でないと、デッドロックが発生します。

ここに画像の説明を入力

于 2016-06-07T04:01:36.077 に答える
0

それは再帰についてです、考えてみてください:

private lock = new ReentrantLock();
public void method() {
      lock.lock();
      method();
}

ロックが再入可能でない場合、スレッドはそれ自体をブロックする可能性があります。

于 2020-04-11T07:10:40.343 に答える