Javaマルチスレッド-4-LOCK

四、ロック

1.ロックの4つの状態

[1]ロックの最適化

ロックの取得と解放のパフォーマンスコストを削減するために、JDK6では「バイアスロック」と「軽量ロック」が導入されました。

その結果、ロックには4つの状態があり、ロックの競合によってアップグレードされます。ロックはアップグレードできますが、ダウングレードはできません。ロックのアップグレードは「ロック拡張」と呼ばれます。

[2]部分ロック状態

ほとんどの場合、ロックにはマルチスレッドの競合がないだけでなく、常に同じスレッドによって複数回取得されます

この状況のパフォーマンスを改善するために、バイアスロックが導入されています

ロックバイアスのスレッドIDは、オブジェクトヘッダーとスタックフレームのロックレコードに格納されます。スレッドが同期ブロックに出入りするときに、CAS操作を実行してロックとロックを解除し、そこにあるかどうかを直接判断する必要はありません。オブジェクトヘッダーのマークワードです現在のスレッドのバイアスロックを指します

存在する場合、スレッドはロックを取得しました。存在しない場合、ロックは軽量ロックに拡張されます。

バイアスロックは、JDK6およびJDK7でデフォルトで有効になっていますが、プログラムの開始から数秒後にアクティブにする必要があります。

この遅延をオフにする必要がある場合は、JVMパラメーターを使用します

-XX:BiasedLockingStartupDelay=0

バイアスロックをオフにする場合は、JVMパラメータを使用します

-XX:-UseBiasedLocking

[3]軽量ロックステータス

ロック:JVMは、現在のスレッドのスタックフレームにロックマークを格納するためのスペースを作成し、オブジェクトヘッダーのDisplaced MarkWordをそれにコピーします。成功した場合は、現在のスレッドがロックを正常に取得したことを意味します。失敗した場合は、ロックの競合があることを意味します。現在のスレッドは、スピンを使用してロックを取得しようとします。

ロック解除:アトミックCAS操作を使用して、Displaced MarkWordをオブジェクトヘッドに戻します。成功した場合はロックの競合がないことを意味し、失敗した場合はロックの競合が発生したことを意味し、ロックがヘビーウェイトロックに拡張されます。

[4]コントラスト

ロックタイプ 利点 不利益 該当シーン
バイアスロック ロックとロック解除を待つ必要はなく
、ロックなしの実行方法と比較してナノ秒の違い(1ナノ秒= 1000 * 1000ミリ秒)があります。
ロックの競争がある場合、それ
は失効ロックの追加消費をもたらします
1つのスレッドのみが同期ブロックにアクセスします
軽量ロック 競合するスレッドがブロックされないため
、プログラムの応答速度が向上します
スレッドがロックを取得できなかった場合、
スピンを使用するとCPUが消費されます
応答速度の追求、
同期ブロックの実行速度は非常に速い
ヘビー級ロック スレッドの競合はスピンを使用せず、CPUを消費しません 競合するスレッドがブロックされ、
応答速度が低下します
スループットを追求し、同期ブロックの実行時間が長くなります

2.フェアロックとアンフェアロック

フェアロック:各スレッドがロックを取得すると、最初にロックによって維持されている待機キューをチェックします。キューが空であるか、現在のスレッドがキューの最初(先頭)である場合、スレッドはロックを取得します。将来的には、FIFOの原則に従って待機キューから取得されます(ロックを取得するために待機するキュー)

不公平なロック:すべてのスレッドがロックの取得を試みることができます

同期は不公平なロックです

java.util.concurrent.locks.ReentrantLockは、パラメーターのないコンストラクターによって作成された不公平なロックです。パラメータ化されたコンストラクタを渡し、trueを渡すと、ロックは公正なロックになります

3.リエントラントロック

リエントラントロックは再帰ロックとも呼ばれ、ロックを取得したスレッドを指します。同期メソッドで同期メソッドを実行すると、ロックを再度取得しなくてもメソッドを直接実行できます。

同期およびjava.util.concurrent.locks.ReentrantLockは再入可能ロックです

4.スピンロック

スレッドは、スレッドコンテキスト切り替えのオーバーヘッドを減らすために、スピンによってロックを取得しようとします

class CasLock {
    
    
    private final AtomicReference<Thread> reference = new AtomicReference<Thread>();

    public void lock() {
    
    
        for (;;) {
    
    
            if (tryAcquire()) {
    
    
                break;
            }
        }
    }

    public void unlock() {
    
    
        for (;;) {
    
    
            if (tryRelease()) {
    
    
                break;
            }
        }
    }

    private boolean tryAcquire() {
    
    
        Thread thread = Thread.currentThread();
        return reference.compareAndSet(null, thread);
    }

    private boolean tryRelease() {
    
    
        Thread thread = Thread.currentThread();
        return reference.compareAndSet(thread, null);
    }

}

5.共有ロックと排他ロック

共有ロック:複数のスレッドがロックを取得できます

排他的ロック:ロックは1つのスレッドにのみ排他的です

java.util.concurrent.locks.ReentrantReadWriteLockの読み取りロックはスレッドによって共有され、書き込みロックはスレッドによって排他的に共有されます

同期およびjava.util.concurrent.locks.ReentrantLockは排他ロックです

6.読み取り/書き込みロック

java.util.concurrent.locks.ReentrantReadWriteLock

読み取り/書き込みロック、読み取りロックと書き込みロックの共存、読み取りロックの共有、書き込みロックの排他的

7.スレッドの互換性とスレッドの反対

スレッドの互換性:操作されるオブジェクトはスレッドセーフではありませんが、さまざまなスレッドセーフの方法を使用して、マルチスレッド環境でオブジェクトがスレッドセーフであることを確認できます。

スレッド反対:操作対象のオブジェクトはスレッドセーフですが、マルチスレッド環境で操作する場合、複数スレッドの同時要求はスレッドセーフではないため、操作オブジェクト自体がスレッドセーフになります。

Javaに敵対する行の例:スレッドクラスの破棄メソッド(@Deprecated)suspendresumeあり、デッドロックが発生する可能性があります

おすすめ

転載: blog.csdn.net/adsl624153/article/details/103865288