Java の同期ロックのアップグレード プロセスは何ですか?

WBOY
リリース: 2023-04-21 16:19:19
転載
1788 人が閲覧しました

同期ロックとは何ですか?ロックは実際にはオブジェクトであり、どのオブジェクトでも使用できます。Java のすべてのオブジェクトはロックです。言い換えれば、Java のすべてのオブジェクトはロックになることができます。
今回は主に同期ロックのアップグレードのルーチンについて話します

synchronizedこれは 4 つの段階を経ます: ロックなし状態、偏ったロック、軽量ロック、重みレベル ロック は、リソース消費量が最も少なくパフォーマンスが最も高いものから、リソース消費量が最も多くパフォーマンスが最も低いものまで順序付けされます。

ロック原則

まず、これらのステータス ロックがロックと呼ばれる理由と、その相互排他原則が何であるかを見てみましょう。

バイアスされたロック

スレッドが 同期コード ブロック に到達し、ロック オブジェクトを取得しようとすると、オブジェクト内の MarkWord をチェックします。スレッド ID、ここに ID がない場合は、独自の ID を保存してロックを取得します。存在する場合は、それが現在のスレッドであるかどうかを確認します。そうでない場合は、CAS がそのスレッドを変更しようとします。存在する場合は、ロック リソースが取得されています。

CAS が変更しようとするロジックの詳細な説明は次のとおりです。これは、バイアスされたロックを保持しているスレッドのステータスをチェックします。まず は、現在の JVM のすべての生き残ったスレッド を走査します。 がバイアスされたスレッド を見つけることができた場合、それはバイアスされたスレッド がまだ生きていることを意味します。 現時点でチェックされているスレッドは、同期されたコード ブロック内のコード を実行していますか? そうであれば、軽量ロックにアップグレードされ、CAS ロックの競合が継続されます。したがって、バイアスされたロックを追加した後は、1 つのスレッドのみがロックを取得し、同期されたコード ブロック内のコードを同時に実行できます。

軽量ロック

オブジェクト ヘッダーの

MarkWordLock Record ポインターが現在のスレッドの仮想マシン スタックを指しているかどうかを確認します。 「はい」の場合は、ロックを使用してビジネスを実行します。そうでない場合は、CAS を実行して変更を試みます。変更が数回失敗した場合は、重量ロックにアップグレードします。

ヘビーウェイト ロック

オブジェクト ヘッダーの

MarkWord で指定されている ObjectMonitor を確認し、所有者が現在のスレッドであるかどうかを確認します (そうでない場合)。 、ObjectMonitorEntryList に Queue をスローし、スレッドを一時停止して、起動されるのを待ちます。

ロックのアップグレード

ロックなし

通常の状況では、

新しい新しいオブジェクトは一時的に ロックフリー状態です 。バイアス ロックはデフォルトで遅延されるため、JVM の起動の最初の 4 秒間はバイアス ロックは発生しませんが、バイアス ロックの遅延設定がオフになっている場合は、匿名のバイアス ロックが新しいオブジェクトに追加されます。つまり、このオブジェクトはバイアス ロックを追加するスレッドを見つけようとしていますが、見つけることができません。これを匿名バイアスと呼びます。保存されるスレッドIDは0000の羅列であり、アドレス情報は一切ありません。

次の構成により、バイアスされたロック遅延をオフにすることができます。

//关闭偏向锁延迟的指令
-XX:BiasedLockingStartuoDelay=0
ログイン後にコピー

偏ったロック

スレッドが

このロック リソースを取得しようとすると、この時点で正常に取得され、偏ったロックになります。 、バイアスされたロック ストレージ スレッド ID。 バイアスされたロックがアップグレードされると、

バイアスされたロックの取り消し

がトリガーされます。バイアスされたロックの取り消しは、安全なポイントまで待つ必要があります。 GC、バイアス ロックの取り消しのコストが高すぎるため、デフォルトでは、バイアス ロックの遅延が最初に実行されます。複数のスレッドが直接競合している場合、バイアス ロックはスキップされ、直接軽量ロックになります。 バイアスロック解除のプロセスを詳しく説明しますが、なぜコストがかかるのでしょうか?スレッドがバイアスされたロックを取得すると、ロック オブジェクト ヘッダーの Mark Work 内のスレッド ID がそれ自身を指します。別のスレッドがロックをめぐって競合し、ロックがアップグレードされると、

前に偏ったロックを取得したスレッドを一時停止します

前に、ワークマークでスレッドIDをクリアし、軽量ロックを追加しますその後、一時停止したロックを復元しますスレッドは の実行を継続します。スレッドが一時停止されるため、ロック エスカレーションを実行する前に安全なポイントまで待機するのはこのためです。 #一般的な安全上のポイント: #GC 実行時

#メソッドが返される前

  • メソッド呼び出し後

  • ##例外がスローされる場所
  • ##ループの終了
  • ##軽量ロック

  • 複数のスレッド間で競合が発生した場合、
  • 軽量ロック

    にアップグレードされます。軽量ロックの効果は、

    CASが取得を試行することに基づいています。ロック リソース
  • アダプティブ スピン ロック

    が使用されます。今回のスピン数は、最後の CAS の成功または失敗と費やされた時間に基づいて決定されます。

  • 軽量ロックは、
競争がそれほど激しくないシナリオに適しています。

1 つのスレッドがロックを取得し、同期コード ブロックを実行すると、プロセスは迅速に完了します。別のスレッドはロックの取得を 1 ~ 2 回試行し、その後再度実行します。これにより、スレッドが長時間待たされることはありません。

ヘビーウェイト ロックヘビーウェイト ロックに到達した場合は、何も言うことはありません。スレッドがロックを保持している場合、他の ロックを取得したい人はハングアップして待機します。ロックを解除すると、順番に目覚めます。 ロックの粗密化とロックの削除

ロックの粗密化/ロックの拡張

ロックの拡張は、Java ファイルのコンパイル時に JIT が行うのに役立つ最適化です。買収とリリース。例えば:###

while(){
   synchronized(){
      // 多次的获取和释放,成本太高,会被优化为下面这种
   }
}
synchronized(){
   while(){
       //  拿到锁后执行循环,只加锁和释放一次
   }
}
ログイン後にコピー

锁消除

锁消除则是在一个加锁的同步代码块中,没有任何共享资源,也不存在锁竞争的情况,JIT编译时,就直接将锁的指令优化掉。 比如

synchronized(){
   int a = 1;
   a++;
   //操作局部变量的逻辑
}
ログイン後にコピー

以上がJava の同期ロックのアップグレード プロセスは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:yisu.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート