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 はバイアス ロックを意味します。
オブジェクト構造は上で紹介したとおりで、Mark-down にさまざまなロック情報が格納されることがわかります。ロック状態がヘビーウェイト ロック (10) の場合、マークダウンは、Monitor オブジェクトへのポインターを保存します。この Monitor オブジェクトは、モニター ロックとも呼ばれます。
同期の動作メカニズムは、JVM が共有オブジェクト内のさまざまな競合状況を検出すると、適切なロック実装に自動的に切り替えます。この切り替えがロックのアップグレードまたはダウングレードです。 (ロックはアップグレードのみ可能でダウングレードはできないと多くの場所で述べられています。実際、この記述は間違いです。書籍「The Art of Java Concurrent Programming」では、バイアスされたロックの場合、ロックにダウングレードできると記載されています。フリー状態、およびバイアスされたロックの取り消しと呼ばれます)。
現在、バイアス ロック、軽量ロック、重量ロックという 3 つの異なるモニター実装があります。スレッドがモニターを保持すると、ロックを取得します。
Monitor in Java は、C の ObjectMonitor に基づいて実装されています。その主なメンバーは次のとおりです:
_owner: ObjectMonitor オブジェクトを保持するスレッドへのポイント
上記の説明からわかるように、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 つの命令があることに注意してください:
での実行結果の正確性。つまり: このスレッド内で観察すると、すべての操作は順序どおりです、あるスレッド内の別のスレッドを観察すると、すべての操作は順序どおりではありません。 ここでの順序付けは volatile とは異なることに注意してください。命令の並べ替えを防ぐために volatile ではありません。
リエントラント ロック
ロック アップグレードのプロセス
。
以上がJavaのSynchronizedの原理は何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。