「アートのJava並行プログラミング」の研究ノート(B)

第2章Javaの並行処理の実装原理のメカニズムの基礎となります

        コードは、Javaバイトコードにコンパイルされた後、バイトコードクラスはJVM、JVMバイトコードの実行にロードされ、CPU上で実行される最終的なアセンブラ命令に変換され、Javaでの同時実行が使用JVMに依存実装とCPUの指示

2.1揮発性のアプリケーション

        並行プログラミングでは同期され、揮発性の共有変数の可視性を確保するための重要な役割、揮発性軽量の同期を、持っています。

  スレッドが共有変数を変更するとき、他のスレッドがこの変更の値を読み取ることができる可視手段。

  volatile変数の修飾子は正しく、実行のコストより低いと同期して、ために揮発性で、スレッドコンテキストスイッチのスケジューリングを起こさないだろう場合。

    1、揮発性の原則の定義と実装

        Java言語仕様での揮発性の定義は、以下:Javaプログラミング言語のアクセス共有変数へのスレッドは、変数が正確で一貫性のある最新情報を確実にするために、スレッドが排他ロックを通してのみ、この変数へのアクセスを確保するために確保すべきで共有することができることができます。Javaは揮発性の提供、およびロックよりもいくつかのケースでは、より便利に。

        そして、実装に依存CPUの観点から揮発性:メモリバリア(メモリバリア)、ライン(キャッシュライン)、アトミック操作(アトミックオペレーション)、バッファラインフィル(キャッシュラインフィル)、キャッシュヒット(キャッシュヒット)、書き込みヒット(ライト・ヒットをバッファ)、書き込みミス(書き込みキャッシュをミス)

        どのように揮発性の視認性を確保するには変更された揮発性の共有変数は、より多くの追加のロックアセンブリコードの書き込み操作、二つのことは、プロセッサのマルチコアロック命令法になります。

        1)現在のデータ処理バッファラインはシステム・メモリに書き戻します

        2)ライトバックメモリは、メモリアドレスに他のCPUのキャッシュデータで動作します有効ではありません

        マルチプロセッサでは、各プロセッサのキャッシュ・コヒーレンシを確保するためには、コヒーレンシプロトコルをキャッシュします、彼らのキャッシュをチェックするために、各プロセッサは、プロセッサが自ら発見したとき、バス上を移動するデータを盗聴により有効期限が切れていませんキャッシュラインに対応するメモリアドレスが、変更されたプロセッサを格納不活性状態に現在のキャッシュラインのセットと、データ変更操作のプロセッサ、プロセッサ・キャッシュ内の再読み出したデータからメモリシステム。

        2つの原則の揮発性の実現:

        1)プロセッサキャッシュ原因ロックプレフィックス命令は、メモリに書き戻されます。

        2)プロセッサのキャッシュ・メモリが原因に書き戻され、他のプロセッサのキャッシュは無効です。

    図2に示すように、揮発性の最適化の使用

        JDK新規契約とチームのパフォーマンスに、キューを最適化する方法で使用されている揮発性の変数、追加バイト7クラスLinkedTransferQueue、内のキューのセット。PaddedAtomicRefernce内部クラスでLinkedTransferQueueわずか64のバイトに加え、揮発性共有変数を言えば、1つの事を有していた(オブジェクト参照が4つのバイトを占め、追加の15個の変数は60バイト、プラス可変親クラスの値の合計であります64バイト)。プロセッサ64は、キューのヘッドノードとテールノードが64バイト未満であれば、ことを意味する部分的に充填されたラインバッファをサポートしていないため、64ビットプロセッサのために、並行プログラミング効率の追加の64のバイトは、改善することができますロックラインバッファ修正するときには、ラインバッファを読み取り、プロセッサ、各プロセッサは、キャッシュコヒーレンシ機構を同じヘッド、複数のプロセッサ下テイルノード、一つのプロセッサをキャッシュします実際には、プロセッサが低いキューエンキューデキュー効率が得られ、独自のキャッシュ内の他のノードの末尾にアクセスすることができますが発生します。追加のバイトの後、バッファラインのヘッドノードおよび末尾ノードを回避する頭部と尾部が変更したとき、ノードが互いにロックしないようにしてもよいです。

     キャッシュラインが64バイト幅のプロセッサでない場合は、アプローチはキャッシュをバッファリングするために多くのバイトを読むために、追加のバイトプロセッサの使用を必要とするので、頻繁に共有変数が(書かれていません、それはいくつかのパフォーマンスをもたらすでしょう消費;)共有変数が頻繁に書き込みでない場合は、ロックのチャンスは非常に小さいですが、また、追加のバイトモードでお互いをロックしないようにする必要はありません、64バイトに追加する必要はありません。

  Java7は、他の追加のバイトモードを使用する必要が役に立たないか、再配置フィールドを排除するため、この追加のバイトモードでは、次のJava7で有効にならないかもしれません。

原理と応用2.2同期の実装

        ヘビー級のロックを同期、様々な最適化されたJava SE 1.6 DUIはそれほど重くなく、同期。オーバーヘッドに起因する問題が導入対策はロック、ロックや他の軽量最適化する傾向があり、性能を減らすためにロックを取得し、解放するために、Java SEの1.6。

        同期を達成するための基礎を同期:Javaですべてのオブジェクトをロックとして使用することができます。特定の形態:通常の同期方法は、ロックオブジェクトの現在のインスタンスであり、静的同期方法は、ロックは、現在のクラスのクラス・オブジェクトであり、ブロック同期コードに対して、オブジェクトのロックブラケットの設定を同期されます。スレッドがブロック/同期アクセス方式を同期しようとすると、あなたが最初のロックを取得する必要があり、ロックは解除時にexitまたは例外をスローする必要があります。

    JVMの実装原則的に同期している:JVMベースの同期は、出入りの監視オブジェクトの実装方法やコードブロック。しかし、二人は同じ実装の詳細ではありません。シンクブロックは、他の同期方法の実施形態が、monitorenterとmonitorexit命令を用いて実現されます。しかし、同期方法は、これら2つの命令を達成するために使用することができます。

    2.2.1 Javaオブジェクトヘッダ

        ロックは、Javaオブジェクトの存在を事前に同期しています。オブジェクトは、アレイ型ストレージオブジェクトヘッダ幅アレイ型、仮想マシン3つの格納ワード幅オブジェクトヘッダ、不使用2ワードである場合。図1は、広い4バイトに等しいです。

    Javaオブジェクトヘッダ:マーク・ワード(ハッシュコード・メモリー・オブジェクト、世代年齢、ロック情報など)、クラスメタデータアドレス(データに格納されたオブジェクトタイプへのポインタ)、配列長(配列の長さ(現在のオブジェクトが配列の場合))

    比較2.2.2アップグレードおよびロック

        :JavaSE1.6では、ロック状態は、ロックフリー状態のステータス、ロック・ステータス・軽量、ヘビー級のロック状態をロックする傾向がありますこれらの状態は、競争とエスカレートします。ロックをアップグレードすることができますが、ダウングレードすることはできませんが、目的は、取得と解放ロックの効率を改善することです。

    1つのバイアスロック

       ほとんどの場合、ロックだけでなく、マルチスレッド化競争が存在しないことである、と常に同じスレッドで複数回取得し、低コストの導入を可能にするためにロックを取得するためのスレッドバイアスロックを  。スレッドがロックアクセスシンクブロックを取得する場合、のみ、オブジェクトヘッダにロックされ、入力しCASシンクブロックを終了した後、スレッドのスレッドIDをロック内に格納されて付勢スタックフレームを記録するロックおよびロック解除操作するために必要とされませんオブジェクトヘッドマークワードをテストする必要がバイアスロックにスレッドポインティングに格納されています。テストが成功した場合は、スレッドがロックを受信したことを示し、テストが成功しなかった場合、あなたは(賛成ロックされている現在の状態を示す)1に設定されているテストマークのWordフラグにロックする傾向がある必要があります:何のセット、CASロックが存在しない場合ロック競合の競争機構と設定した場合、CASはバイアスされ、現在のスレッドにオブジェクトヘッドポイントのロックを使用しようとします。

     (1)バイアスされたロック失効

        偏ったロック機構を使用することが競争のロックを解除するまで、バイアス競争をロックするので、他のスレッドの試みは、バイアスロックしているスレッドが解放されます開催しました。

        バイアスは、グローバルセキュリティ点まで待機する必要があります(バイトコードなしでは、この時点で実行されている)、失効ロック。これは、最初のバイアスロックしているスレッドを中断する必要があり、その後、スレッドがアクティブでない場合、オブジェクトはロックフリー状態への最初のセットであり、生きているロックバイアス保持しているかどうかをチェックします。スレッドがまだ生きている場合は、スタックの偏ったロックが実行されますと最後のウェイクアップスレッドをロックバイアスとしてオブジェクトロックバイアスされたレコードを横断、レコードのWordのスタックをマークし、オブジェクトヘッドのいずれか他のスレッドに有利になるように偏った再、またはオブジェクトを復元するロックなしまたはタグをロックするには適していません。

     (2)クローズバイアスロック

    Javaの6とJava7のデフォルトはバイアスされ、ロックを開始することです。アプリケーションの開始後わずか数秒で活性化されます。遅延を閉じ、すぐに開始するBiasedLockingStartupDelay = 0セット:JVMパラメータ-XXを使用することができます。あなたは-XXを使用することができます。-UsebiasedLocking-falseが閉じられたロックをバイアスされ、その後、プログラムは軽量ロック状態を入力します。

    2軽量ロック

    (1)軽量ロックロック

        事前同期ブロックを実行するためのスレッド、JVMは、ロックを格納するために現在のスレッドのスタックフレームスペースに作成され、マークのWordのオブジェクトヘッドが正式に「ずれマークことば」として知られているレコードを、ロックするコピーされます。スレッドは、ポインタCASする点にオブジェクトヘッダMarkWordロック・レコードを交換しようとします。成功した場合、現在のスレッドがロックを取得するには、それが失敗した場合、別のスレッドのロック競合を表し、現在のスレッドがスピンロックを取得するために使用しようとします。

    (2)軽量ロックロック解除

        ロック解除時に軽量、マークWordがオブジェクトにヘッド裏に置き換えられます変位人工原子をCAS使用しますが、成功した場合、それは競争が発生していないがあることを意味します。それが失敗した場合、競争があり、現在のロックを表し、ロックはヘビー級のロックを膨潤します。

        スピンはCPUを消費しますので、(そのようブロックするロックを獲得するためのスレッドなど)の不要なスピンを避けるために、ロック・エスカレーションにヘビー級のロックと、軽量ロック状態に戻りません。ロックがこの状態にあるときに、別のスレッドがスレッドがこれらのスレッドを起動しますロックを保持しているロックを解放したときにブロックされるロックを取得しようとしている、スレッドは勝利の戦いロックの新ラウンドを目覚めさせます。

    ロックの長所と短所を比較する3、

 
 

アトミック2.3の動作原理

    実行後は、一部の後に行うことができない別の操作を実行するために中断された時にこの操作が細分化を行っていないことをアトミック操作手段はすべてを完了する必要があります。

    1、関連用語

    キャッシュライン(キャッシュライン)、比較交換(比較とスワップ)、CPUのパイプライン(CPUパイプライン)、メモリ順序の競合

    図2に示すように、プロセッサは、アトミック動作を実現する方法であります

        プロセッサのために、それは同時に、アトミック操作のみ1つのプロセッサがデータを処理し、アトミック操作は不可分であると言うことです。2つの一般的な方法があります。一つはバスロックで原子性を確保するためであり、他は、原子キャッシュロックによって保証されています。

        バスキー:他のプロセッサを要求するバス上の信号は、確実にするために、信号が排他的にプロセッサメモリを発行できるように、ライブにブロックされる時にバスロックは、このプロセッサの出力は、プロセッサが提供するLOCK#信号を使用することです原子操作。

        キャッシュロック:キャッシュロックを最適化バスロックアウトするように設計されています。ロック時のバスがロックされているので、他のプロセッサは、ロックが解除されるためだけに待つことができ、他のデータを扱うことができません。しかし、キャッシュのロックは、この影響を軽減することができます。彼は、キャッシュ・ライン・プロセッサ場合は、キャッシュメモリ領域を参照し、ロック動作時にロックされ、それはロック動作がメモリに書き戻される行うときに、プロセッサはバス上公言ロック信号ではなく、直接内部を変更しますキャッシュ・コヒーレンシ機構防止データは、同時に2つ以上のプロセッサキャッシュでメモリ領域を変更するために彼のキャッシュ・コヒーレンシ機構を備えたメモリアドレスは、アトミックな動作を保証するために、他のプロセッサのキャッシュへの書き込みバックがロックされていますデータラインは、キャッシュラインが無効であることを確認してください。

  しかし、どちらの場合も、プロセッサは、キャッシュのロックを使用していません。

    1)最初のケースである:データは複数のデータ・キャッシュ・ライン(キャッシュライン)を横切ってプロセッサ・キャッシュ、または動作内で動作させることができない場合、プロセッサは、バスロックを呼び出します。

    2)第2の状況は次のとおりです。一部のプロセッサは、キャッシュロックをサポートしていません。ロックメモリ領域は、キャッシュラインのプロセッサバスロックで呼び出される場合であっても。

  上記の2つのメカニズムがロックプレフィックス命令を用いて実現することができるために。

    3、Javaのアトミック操作を実装する方法

            Javaでは使用してロックをし、CASの循環アトミック動作を保証する方法を

           (1)  サイクルのCAS: JVMはCAS動作プロセッサの実装によって提供される公式CMPXCHG命令を使用します。基本的な考え方は、成功するまで、CASサイクルによって操作されます。

            三つの原子の(2)CAS操作

                  1)ABA問題

          ソリューションは、バージョン番号が変数、バージョン番号がインクリメントされる各変数の更新の前に添加され、バージョン番号です。ABAはJDK1.5 AtomicStampedReferenceを使用して問題を解決するために、このクラスののcompareAndSetアクションが現在の基準は、現在のフラグが予想されるフラグと等しいかどうかを予想参照及びチェックに等しい方法チェックで、全てがアトミックフラグや参照に等しい場合指定された更新値に値

        2)長いサイクル時間オーバヘッド大きいです。時間が成功したスピンCASでない場合、それは非常に大きなCPUの実行コストをもたらすでしょう。

          JVMは、プロセッサによって提供される一時停止命令をサポートできる場合、ので、いくつかの効率改善が存在するであろう。

          pauseコマンドは、2つの効果があります:最初、それはCPUが、いくつかのプロセッサ時間遅れで、実行するために実装依存の遅延時間をあまりにも多くのリソースを消費しないように、命令のパイプライン実行(デパイプラインを)遅らせることができますそれはゼロです。

                    第二に、それはCPUのパイプラインによって引き起こされるため、メモリの競合に順序(メモリー注文違反が)CPUの効率を向上させるためには、(CPUパイプライン・フラッシュ)がクリアされたループを終了避けることができます。

        3)のみ共有変数アトミック動作を保証

          ソリューションは、複数の共有変数が動作するには、共有変数に結合されていることができます。CASの操作に複数の変数にオブジェクトを置くことについてです。

             (3) ロック機構スレッドが入力したい場合には、ロック機構のロックを操作するロックを獲得するスレッドの専用メモリ領域保証しなくJavaで複数のロック、バイアスされたロックに加え、JVMがロックループCASを達成するための方法であり、環状CASを使用するときにシンクブロックを取得し、シンクブロックを出るときにロックを解除するために使用されるCASサイクル。

2.4まとめ

おすすめ

転載: www.cnblogs.com/mYunYu/p/12450324.html