Javaの偽共有(偽共有)とキャッシュライン(キャッシュライン)およびいくつかのロックのパフォーマンス比較

まず、キャッシュライン(キャッシュライン)

CPUのキャッシュはキャッシュライン単位でキャッシュされており、複数のスレッドが異なる変数を変更し、これらの変数が同じキャッシュラインにある場合、お互いのパフォーマンスに影響を及ぼします。

キャッシュラインは通常64バイトで、メインメモリ内のアドレスのブロックを効果的に参照します。Javaのlong型は8バイトであるため、8つのlong型変数をキャッシュラインに格納できます。

2つ目は、キャッシュラインの充填

誤った共有を解決する最も簡単な方法はパディングです。たとえば、longは8バイトを占め、Javaオブジェクトヘッダーは32ビットシステムでは32ビット(4バイト)、64ビットシステムでは64ビットを占めます( 8バイト)。キャッシュラインは64バイトで、6つのlongを埋めることができます(1つのlongと6はlongを埋めるために使用され、合計:8 + 6 * 8 = 56バイト)。これは、64ビット仮想マシンで正確に64ワードを占めますセクションでは、32ビット仮想マシンの下にキャッシュラインが1つしかないため、複数のVolatileLongキャッシュラインを回避できます。

javaは、キャッシュライン全体を埋めるために、1つの長いフィールドと6つの長いフィールドを使用して、誤った共有を回避していることがわかります。

3つ、@ sun.misc.Contendedアノテーション


1. jdk8が@ sun.misc.Contendedの使用を開始しました。このアノテーションをフィールドに追加すると、フィールドが別のキャッシュライン(キャッシュライン)を占有して、誤った共有を回避できます。仮想マシンを起動するときに、-XX:-RestrictContendedパラメータを指定してください


2. jdk7の仮想マシンは不要なフィールドを最適化するため、7 longを使用してキャッシュラインを埋めることは不可能になります。jdk7の使用は避けてください

4番目に、仮想マシンオブジェクトのフィールドシーケンスが自動的に配置されます。


HotSpot JVMの場合、すべてのオブジェクトに2ワードのオブジェクトヘッダーがあります。最初のワードは、24ビットのハッシュコードと8ビットのフラグビット(ロックステータスやロックオブジェクトなど)で構成されるマークワードです。2番目の単語は、オブジェクトが属するクラスへの参照です。配列オブジェクトの場合は、配列の長さを格納するために追加のワードが必要です。各オブジェクトの開始アドレスは、パフォーマンスを向上させるために8バイトに揃えられます。したがって、オブジェクトをカプセル化する際の効率のために、オブジェクトフィールド宣言の順序は、バイトサイズに基づいて次の順序に並べ替えられます:
    double(8)およびlong(8)
    ints(4)およびfloat(4)
    short(2)そして、chars(2)
    booleans(1)およびbytes(1)
    参照(4/8)
    <サブクラスフィールドは上記の順序を繰り返します>

5、いくつかのスレッド共有パフォーマンスの比較


シングルスレッドロックフリー:1(シングルスレッドロックフリー条件のパフォーマンスに基づいて、遅くなります)
シングルスレッドロックロック:33
シングルスレッドcasロック:19
シングルスレッドvolatile:16
マルチスレッドロックロック:747
マルチスレッドcasロック:100

おすすめ

転載: blog.csdn.net/eguid/article/details/108638469