JavaのSynchronizedの原理は何ですか
ソースコードレベルの解析 Synchronized
オブジェクト構造
Synchronized は Java における暗黙的なロックであり、取得ロックと解放ロックは両方ともこれは暗黙的であり、JVM の操作に完全に委ねられています。Synchronized キーワードを理解する前に、最初に学習すべき知識ポイントは Java オブジェクトの構造です。これは、Synchronized ロックは Java オブジェクトに格納されているためです。Java オブジェクトの構造は次のとおりです。 :
Java オブジェクトは、オブジェクト ヘッダー、インスタンス データ、フィル データの 3 つの部分で構成されていることが明確にわかります。次に、オブジェクト構造の簡単な分析を行います。
マークダウン: オブジェクト マーク フィールドは 8 バイトを占め、オブジェクト マークに関する情報を格納するために使用されます。ロックのマークビット. 図から、ハッシュ値、軽量ロックフラグ、バイアスロックフラグなどが存在することがわかります。
Klass ポインタ: クラス オブジェクトの型ポインタ。現在のオブジェクトが属するクラスへのポインタです。デフォルトでは、jdk1.8 は圧縮ポインタをオンにし、4 を占有します。圧縮ポインタをオフにします。圧縮ポインタは 8 バイトを占有します。
オブジェクトの実際のデータ: この部分にはオブジェクトのすべてのメンバー変数が含まれます。サイズは各メンバー変数によって決まります。たとえば、byte は 1 バイト、int は 4 バイトを占め、等
記入してください: この部分はスペースを補完するためのものであり、プレースホルダーとして機能します。これは、HotSpot 仮想マシンのメモリ管理システムでは、オブジェクトの開始アドレスが次である必要があるためです。は 8 バイトの整数倍であるため、オブジェクト インスタンスが整列していない場合は、パディングする必要があります。
マークダウンロックタイプのマークには、ロックなし、偏りロック、軽量ロック、重量ロック、GCマークの計5種類があることが分かります。したがって、2 ビットのマークのみを使用すると完全に表現できないため、バイアス ロック マークが導入されます。つまり、001 はロックなし、101 はバイアス ロックを意味します。
Monitor オブジェクト
オブジェクト構造は上で紹介したとおりで、Mark-down にさまざまなロック情報が格納されることがわかります。ロック状態がヘビーウェイト ロック (10) の場合、マークダウンは、Monitor オブジェクトへのポインターを保存します。この Monitor オブジェクトは、モニター ロックとも呼ばれます。
同期の動作メカニズムは、JVM が共有オブジェクト内のさまざまな競合状況を検出すると、適切なロック実装に自動的に切り替えます。この切り替えがロックのアップグレードまたはダウングレードです。 (ロックはアップグレードのみ可能でダウングレードはできないと多くの場所で述べられています。実際、この記述は間違いです。書籍「The Art of Java Concurrent Programming」では、バイアスされたロックの場合、ロックにダウングレードできると記載されています。フリー状態、およびバイアスされたロックの取り消しと呼ばれます)。
現在、バイアス ロック、軽量ロック、重量ロックという 3 つの異なるモニター実装があります。スレッドがモニターを保持すると、ロックを取得します。
Monitor in Java は、C の ObjectMonitor に基づいて実装されています。その主なメンバーは次のとおりです:
-
_owner: ObjectMonitor オブジェクトを保持するスレッドへのポイント
- #_WaitSet: スレッド キューを待機状態に保存します。つまり、wait() メソッドを呼び出すスレッドです。 ##_EntryList: スレッド キューを待機中のロックに保存します。ブロック状態
- _count: _WaitSet _EntryList 内のノード数のおおよその合計
- _cxq: ロックを競合する複数のスレッドが最初に保存しますこの一方向のリンク リスト
- _recursions: 再エントリの数を記録します
- _object: 保存されたモニター オブジェクト
- Get Monitor オブジェクトのスレッドが _owner 領域に入ると、_count は 1 になります。スレッドが wait() メソッドを呼び出すと、Monitor オブジェクトが解放され (ロックが解除され)、_owner が元の状態に戻ります。空および_count-1。この時点で、スレッドは _WaitSet キューに入り、起動されるのを待ちます。
上記の説明からわかるように、synchronized キーワードを使用してロックを取得する鍵は、各オブジェクトのオブジェクト ヘッダーにあります。これは、synchronized() 括弧内に格納されているオブジェクトがロックを取得できる理由も説明しています。 特徴。
同期機能
原子性
原子性とは、操作が完了したか、または完了していないことを意味します。半分完了した、つまり操作が完了していないということはありません。可能です。中断されます。
synchronized は、同時に 1 つのスレッドだけがロックを取得し、コード ブロックに入ってコードを実行することを保証します。これが理解できない場合は、次のシーンを想像してください。トイレは1つのピットで、複数人が一緒にトイレに行くという非文明的な現象を防ぐために、トイレにも施錠されています。トイレを使用する人は全員、トイレ管理者に支払いをしなければなりません。支払い後、トイレに行く前にロックを受け取ることができます。トイレを使用した後は、トイレ管理者に鍵を返却することができます。同期はトイレ管理者なので、一度に 1 人だけが鍵を取得でき、トイレ使用後は全員が鍵を返却する必要があります。
次に、次の同期追加メソッドを参照してください:
public static void add() { synchronized (Demo.class) { counter++; } }
それをデコンパイルしてコードを表示します:
javap -v -p Demo
public static void add(); descriptor: ()V flags: ACC_PUBLIC, ACC_STATIC , ACC_SYNCHRONIZED Code: stack=2, locals=2, args_size=0 0: ldc #12 // class 2: dup 3: astore_0 4: monitorenter 5: getstatic #10 // Field counter:I 8: iconst_1 9: iadd 10: putstatic #10 // Field counter:I 13: aload_0 14: monitorexit 15: goto 23 18: astore_1 19: aload_0 20: monitorexit 21: aload_1 22: athrow 23: return Exception table:
次のことができます。明らかにモニターに関連する 2 つの命令があることに注意してください:
- #monitorenter: 同期フラグ ACC_SYNCHRONIZED があると判断した後、最初にこのメソッドに入ったスレッドが最初に Monitor の所有者になります。このときのカウンタは 1
- monitorexit: 実行時、終了後、カウンタは -1 になり、0 に戻り、他の開始スレッドによって取得されます。
- スレッドがロックする前に、メインメモリから共有変数の最新の値を読み取るために、作業メモリ内の共有変数の値をクリアする必要があります。
- スレッドがロックを解放すると、共有変数の値がメイン メモリに更新される必要があります。
- synchronized の可視性は、オペレーティング システムのカーネル ミューテックスの実装に依存します。これは、JVM のロックとロック解除に相当します。コード ブロックを終了するときは、共有変数を更新する必要があります。この点 volatile キーワードとは異なり、volatile キーワードの可視性はメモリ バリア (メモリ バリアとも呼ばれます) に依存します。
での実行結果の正確性。つまり: このスレッド内で観察すると、すべての操作は順序どおりです、あるスレッド内の別のスレッドを観察すると、すべての操作は順序どおりではありません。 ここでの順序付けは volatile とは異なることに注意してください。命令の並べ替えを防ぐために volatile ではありません。
リエントラント ロック
リエントラント ロックの概念は非常に単純です。つまり、スレッドは保持しているオブジェクト ロックを複数回取得できます。この種のロックはリエントラント ロックです。ロックには、同じ数のロックを解放する必要もあります。同期ロックオブジェクトには、ロックを取得した回数、つまりリエントラントの数を記録するためのカウンタがあります。
ロック アップグレードのプロセス
同期ロックには、ロックなし、バイアスされたロック、軽量ロック、および重量ロックという 4 つの代替アップグレード状態があります。これらの状態は、競合によって徐々にエスカレートします。
完全なロックアップグレード図は後で追加されます。
以上がJavaのSynchronizedの原理は何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









Java の乱数ジェネレーターのガイド。ここでは、Java の関数について例を挙げて説明し、2 つの異なるジェネレーターについて例を挙げて説明します。

Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

Java での日付までのタイムスタンプに関するガイド。ここでは、Java でタイムスタンプを日付に変換する方法とその概要について、例とともに説明します。

Java は、初心者と経験豊富な開発者の両方が学習できる人気のあるプログラミング言語です。このチュートリアルは基本的な概念から始まり、高度なトピックに進みます。 Java Development Kit をインストールしたら、簡単な「Hello, World!」プログラムを作成してプログラミングを練習できます。コードを理解したら、コマンド プロンプトを使用してプログラムをコンパイルして実行すると、コンソールに「Hello, World!」と出力されます。 Java の学習はプログラミングの旅の始まりであり、習熟が深まるにつれて、より複雑なアプリケーションを作成できるようになります。
