次のようなものを想像してください。
function A():
lock (X)
B()
unlock (X)
function B():
A()
次に、A を呼び出します。次のことが起こります。
- Aを入力し、Xをロックします
- Bに入ります
- もう一度 A を入力し、X を再びロックします
A の最初の呼び出しを終了していないため、X はまだロックされています。これは再入と呼ばれます - 関数 A がまだ戻っていない間に、関数 A が再度呼び出されます。A が何らかのグローバルな静的状態に依存している場合、これにより「再入バグ」が発生する可能性があります。静的状態が関数の終了からクリーンアップされる前に、関数が再度実行され、半分計算された値が最初の部分と衝突します。 2回目の呼び出し。
この場合、すでに保持しているロックに遭遇します。ロックが再入可能である場合、すでにロックを保持している同じスレッドであることが認識され、通過させられます。そうしないと、永久にデッドロックになります。すでに保持しているロックを待機することになります。
Java ではlock
、synchronized
再入可能です。ロックがスレッドによって保持されていて、スレッドが同じロックを再取得しようとすると、それが許可されます。したがって、上記の疑似コードを Java で記述した場合、デッドロックは発生しません。