2 つのスレッドが同期ブロックにアクセスしようとするとどうなりますか?
スレッドの 1 つがどこかでキューに入れられ、後でそのスレッドにアクセスするか、または試行が失敗した場合にスレッドが放棄されるか?
2 つのスレッドが同期ブロックにアクセスしようとするとどうなりますか?
スレッドの 1 つがどこかでキューに入れられ、後でそのスレッドにアクセスするか、または試行が失敗した場合にスレッドが放棄されるか?
同期ブロックを意味すると仮定すると、1 つのスレッドがモニターを取得し、もう 1 つのスレッドがモニターが解放されるまでブロックします。
以下を含む詳細については、JLS のセクション 14.19およびセクション 17.1を参照してください。
同期ステートメント (§14.19) は、オブジェクトへの参照を計算します。次に、そのオブジェクトのモニターでロック アクションを実行しようとし、ロック アクションが正常に完了するまで先に進みません。ロック アクションが実行された後、同期ステートメントの本体が実行されます。ボディの実行が通常または突然に完了すると、同じモニターでロック解除アクションが自動的に実行されます。
(私のものを強調してください。)
他のセマンティクス (タイムアウトなど) が必要な場合は、パッケージ内のタイプのいずれかを使用して、やjava.util.concurrent.locks
などのメソッドを使用できるようにする必要があります。tryLock()
tryLock(long time, TimeUnit unit)
スレッドの 1 つがどこかでキューに入れられますか
はい、JVM でキューに入れられ、実行中のスレッドがロックを解放するまで待機します。
試行が失敗した場合、スレッドはあきらめますか
いいえ、JVM が有効になるまで試行を続けます。ただし、別のスレッドが同期されたコードを実行している間は試行しません (タイムアウトが指定されていない場合)。
同期ブロックを試みて成功したThreadA
としましょう。さて、終わるまで待ちます。その間に、が来るとします。ブロックが何らかのスレッドによって実行されていることがわかり、 と同じキューで待機します。または実行する機会が与えられたとき。ThreadB
sb
ThreadB
ThreadA
ThreadB
ThreadC
sb
ThreadA
ThreadB
ThreadA
ThreadC
したがって、技術的には、キューではなく、同様のデータ構造です。
そのうちの 1 つは、必要に応じて (無限ループを実行する最初のスレッドなど) 永久に待機しますが、それはかなり悪い設計です。コード実行の同期にタイムアウトはありません。
JLS から:
同期されたステートメントは、実行中のスレッドに代わって相互排他ロックを取得し、ブロックを実行してから、ロックを解放します。実行中のスレッドがロックを所有している間は、他のスレッドがロックを取得することはできません。
ブロックが別のスレッドによって実行されている場合synchronized
、両方のスレッドが待機します。それ以外の場合、1つのスレッドでの作業が許可され、別のスレッドは最初のスレッドがそのジョブを完了するまで待機します。