ここにシナリオがあります
たとえば、2 つのスレッドが両方とも同じコードにアクセスし、そのコードには変数があります。
int a=200;
スレッド A が入り、その値を a=300 に変更します。
スレッド B がこの変数にアクセスすると、スレッド B は 200 または 300 を取得しますか?
ここにシナリオがあります
たとえば、2 つのスレッドが両方とも同じコードにアクセスし、そのコードには変数があります。
int a=200;
スレッド A が入り、その値を a=300 に変更します。
スレッド B がこの変数にアクセスすると、スレッド B は 200 または 300 を取得しますか?
2つのスレッドは、固定された順序で実行されることが保証されていません。Aでの操作は、Bでの操作に先行する可能性があります(ただし、操作が引き続き独自のスレッド内で順番に流れる場合)。
したがって、同期がないと、AはBがアクセスする前または後に値を変更する可能性があります。AがBの前にそれを変更した場合、Bは300を認識します。それ以外の場合、Bは200を参照します。
以下の状態チャート図は、スレッドの状態を示しています。
Thread.sleep(milliseconds), Thread.sleep(milliseconds, nanoseconds);
あなたの例については、どのスレッドBが200または300を取るかわかりません。メソッドが同期されるため、両方のスレッドを同時に開始すると、スレッドBは200を参照する必要があります(1番目または300の場合)。
コンパイラの最適化により、スレッドがデータをキャッシュし、最初のスレッドの変更が 2 番目のスレッドに表示されない場合があります。マルチスレッド環境での問題を回避するために、共有データに「揮発性」が使用される場所です。
補遺-さて、同期ではなく、スレッド全体の変数の変更の可視性について話していました。
スレッドがコードに同時にアクセスする場合、jvmレベルのスレッド優先度に従って発生します。どのスレッドがコードにアクセスするかは保証できません。同期されている場合、スレッドBはスレッドAがリソースを解放するまで待機する必要があります。
上記の実行の結果は、整合性モデルによって異なります。
シーケンシャル整合性モデルでは、実行の結果、すべての命令がグローバルな順序で実行されます。このような場合、threadB は値 300 を取得します。
ただし、最新のマシンは、すべての同期 (メモリ フェンス命令) 操作のみがグローバルな順次順序で発生する、より弱い整合性モデルを使用しています。
スレッド A のストアが完了した後にスレッド B のロードが発生した場合、スレッド B は値 = 300 を取得します。これは、キャッシュ コヒーレンス プロトコルによって保証されます。ただし、スレッド B のロード命令がスレッド A のストアの前またはストアと共に発生した場合 (何らかの最適化により)、スレッド B の共有変数の値は未定義です。これは、バス操作を介したスレッド B のロードとスレッド A のストアとの間の競合状態の結果です。