コード スニペット - 1
class RequestObject implements Runnable
{
private static Integer nRequests = 0;
@Override
public void run()
{
synchronized (nRequests)
{
nRequests++;
}
}
}
コード スニペット - 2
public class Racer implements Runnable
{
public static Boolean won = false;
@Override
public void run()
{
synchronized (won)
{
if (!won)
won = true;
}
}
}
最初のコード スニペットで競合状態が発生しました。これは、(Integer 型の) 不変オブジェクトのロックを取得していたためだと理解しました。
私は 2 番目のコード スニペットを作成しましたが、これもまた、'Boolean' が不変であることに影響されません。しかし、これは機能します (出力実行に競合状態は表示されません)。以前の質問の解決策を適切に理解した場合、以下は、問題が発生する可能性のある 1 つの方法です。
- スレッド 1 が指すオブジェクト (A など) のロックを取得します。
won
- スレッド 2 は、 が指すオブジェクトのロックを取得しようとし
won
、A の待機キューに入ります。 won = true
スレッド 1 は同期ブロックに入り、A が false であることを確認し、 (A はレースに勝ったと考えている) と言って新しいオブジェクト (B など) を作成します。- 'won' は B を指すようになりました。スレッド 1 はオブジェクト A のロックを解放します (もはや によって指されていません
won
) 。 - ここで、オブジェクト A の待機キューにあったスレッド 2 が起動され、オブジェクト A のロックが取得されますが、オブジェクト A はまだロックされています
false
(不変にそうです)。今度は同期ブロックに入り、自分も勝ったと想定しますが、これは正しくありません。
2 番目のコード スニペットが常に正常に動作するのはなぜですか??