データを同時に共有し、一貫性を確保するためのツールとして、ロックは JAVA プラットフォーム上に複数の実装があります (synchronized ロックや ReentrantLock など)。これらの既に書き込まれたロックは開発に便利ですが、ロックの具体的な性質や種類についてはほとんど言及されません。このシリーズの記事では、JAVA での一般的なロック名と特徴を分析して、質問に答えます。
4. リエントラントロック:
この記事では、JAVA での ReentrantLock だけではなく、広い意味でのリエントラント ロックについて説明します。
リエントラント ロック (再帰ロックとも呼ばれます) は、同じスレッドの外側の関数がロックを取得した後、内側の再帰関数にはロックを取得するためのコードがまだ残っていますが、影響を受けないことを意味します。
JAVA 環境では、ReentrantLock と synchronized は両方とも再入可能なロックです。
使用例を次に示します。
次のようにコードをコピーします。
パブリック クラス テストは Runnable{ を実装します
public synchronized void get(){
System.out.println(Thread.currentThread().getId());
セット();
}
public synchronized void set(){
System.out.println(Thread.currentThread().getId());
}
@オーバーライド
public void run() {
得る();
}
public static void main(String[] args) {
テスト ss=new Test();
新しいスレッド(ss).start();
新しいスレッド(ss).start();
新しいスレッド(ss).start();
}
}
どちらの例の最終結果も正しく、同じスレッド ID が 2 回連続して出力されます。
結果は次のとおりです。
次のようにコードをコピーします。
ねじ山: 8
ねじ山: 8
ねじ山: 10
ねじ山: 10
ネジ長: 9
ネジ長: 9
リエントラント ロックの最大の役割は、デッドロックを回避することです。
スピンロックを例に挙げてみましょう。
次のようにコードをコピーします。
パブリック クラス SpinLock {
private AtomicReference<Thread> owner =new AtomicReference<>();
パブリック void ロック(){
スレッド電流 = Thread.currentThread();
while(!owner.compareAndSet(null, current)){
}
}
public void ロック解除 (){
スレッド電流 = Thread.currentThread();
owner.compareAndSet(current, null);
}
}
スピンロックの場合:
1. 同じスレッドが lock() を 2 回呼び出すと、2 回目に呼び出されるロック位置がスピンします。デッドロックが発生した場合、それはロックが再入可能ではないことを意味します。 (ロック関数では、そのスレッドがロックを取得したスレッドであるかどうかを確認する必要があります)
2. 問題 1 が解決されていれば、最初にunlock()が呼び出された時点でロックは解除されています。実際にはロックを解除する必要はありません。
(統計にはカウント時間を使用します)
修正後は以下の通りです。
次のようにコードをコピーします。
パブリック クラス SpinLock1 {
private AtomicReference<Thread> owner =new AtomicReference<>();
プライベート int カウント =0;
パブリック void ロック(){
スレッド電流 = Thread.currentThread();
if(current==owner.get()) {
カウント++;
戻る ;
}
while(!owner.compareAndSet(null, current)){
}
}
public void ロック解除 (){
スレッド電流 = Thread.currentThread();
if(current==owner.get()){
if(カウント!=0){
カウント - ;
}それ以外{
owner.compareAndSet(current, null);
}
}
}
}
このスピン ロックはリエントラント ロックです。