Javaの深い分析-同時原子量

2145 ワード

Volitale
同時実行中、ロックは主に2つの特性を提供します:反発と可視
同時の場合、1つのスレッドが先に来て、オブジェクトに鍵をかけて、他のスレッドは後ろに並ぶしかありません.この反発は私たちに操作の原子性をもたらします.つまり、同時の場合、1つの操作は他のスレッドの影響を受けません.
また、各スレッドは変数を読み出す際に、自分で1部キャッシュする、つまり、次の読み出し操作でメモリを通過せずに直接キャッシュを取る可能性があります.もちろん、同時条件ではスレッド共有の変数に問題があるのは当然ですが、各スレッドが1つの変数にアクセスするたびにメモリから値を再読み込み、この変数はスレッドごとに可視性があると考えられます
もちろん、反発する必要がなく、可視性を保証するだけで、Javaはより軽量な文法volitaleを提供し、volitaleで修飾された変数を保証することができます.
  • 可視性
  • 指令再配列防止
  • コードを実行するとき、コードの順序はA->B->Cで、CPUは実行効率のために、その順序を乱す可能性があります.もちろん、なぜ私たちは単一スレッド条件で実行するのが秩序化されているのか.なぜなら、命令の並べ替えはas-if-serialの意味に従っているからです.つまり、どのように並べ替えても、CがAとBに依存している場合のように、結果に影響しません.Aが実行されるのは、AとBの両方が実行されてからです.
    volitaleは、i++の実行プロセスのように原子性をサポートしていないことが明らかになった.
  • メモリからi
  • を取り出す.
  • iを1
  • 加算
  • 結果をi
  • に割り当てる.
    volitaleには読み取り-書き込みロックという書き方があり、それ自体が矛盾しています.私たちがこのような書き方を使うとき、読み取りは厳密ではないと思います.このモードの最も基本的な応用を超えたら、この2つの競争の同期メカニズムを結合することは非常に困難になります.
        private volatile int value;
    
        public int getValue() { return value; }
    
        public synchronized int increment() {
            return value++;
        }
    

    Unsafe
    名前の通り、Unsafeは非常に安全ではないクラスです.
    そしてUnsafeを発注して以下の機能を提供する:
  • メモリアドレス
  • を直接操作する.
  • 回復と保留スレッド
  • オープンアセンブリ、CPUレベルのCAS[1]動作
  • Jdkと発注はUnsafeの下で確立されていると考えられますが、その構造関数はクラスローダによってカプセル化されており、アウトソーシングの下で反射によって取得できますが、Unsafeクラスを使用すると、必ずそれをよく知っておいてください.
    Atomicシリーズクラス
    自分のオブジェクトを原子化したい場合は、AtomicReferenceは良い選択です.AtomicReferenceの内部にはUnsafe、メモリオフセットアドレスが維持されており、原子操作の入り口も開いています.
    public class AtomicReference implements java.io.Serializable {
    
        private static final Unsafe unsafe = Unsafe.getUnsafe();
        private static final long valueOffset;
        private volatile V value;
    
        static {
            try {
                valueOffset = unsafe.objectFieldOffset
                    (AtomicReference.class.getDeclaredField("value"));
            } catch (Exception ex) { throw new Error(ex); }
        }
    
        // ...
    }
    

    私たちが自分のオブジェクト配列を原子化したいなら、AtomicReferenceArrayは良い選択です.
    自分の数値変数を原子化したい場合は、一連のAtomicInteger、AtomicDoubleを選択することができます.
    それらの実装はほぼ同じであり,内部はUnsafeに基づいて構築されているが,ここでは詳細に議論しない.
  • 無ロックスピン同期CAS動作詳細↩