Javaロックのブロックロックの説明とコードの例

2324 ワード

ロックはデータを同時共有し、一貫性を保証するツールとして、JAVAプラットフォームではsynchronizedやReentrantLockなど多くの実装があります.これらのすでに書かれたロックは、開発に便利を提供していますが、ロックの具体的な性質やタイプはあまり言及されていません.このシリーズでは、JAVAの下でよく見られるロックの名前と特性を分析し、疑問に答えます.
ブロックロック
ブロックロックは、スピンロックとは異なり、スレッドの動作状態を変更します.JAVA環境ではスレッドThreadには次のような状態があります.
1、新規ステータス
2、準備状態
3、運転状態
4、ブロック状態
5、死亡状態
ブロックロックは、スレッドをブロック状態にして待機させるといってもよく、対応する信号(起動、時間)が得られると、スレッドの準備準備準備完了状態に入ることができ、準備完了状態のすべてのスレッドが競争することで、実行状態に入ることができる.
JAVAでは、退出、閉塞状態または閉塞ロックを含むことができる方法として、synchronizedキーワード(その中の重量ロック)、ReentrantLock、Objectがある.wait()otify(),LockSupport.park()/unpart()(j.u.cでよく使われる)
次はJAVAブロックロックの例です.

package lock;

import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.concurrent.locks.LockSupport;

public class CLHLock1 {
  public static class CLHNode {
    private volatile Thread isLocked;
  }

  @SuppressWarnings("unused")
  private volatile CLHNode                      tail;
  private static final ThreadLocal              LOCAL  = new ThreadLocal();
  private static final AtomicReferenceFieldUpdater UPDATER = AtomicReferenceFieldUpdater.newUpdater(CLHLock1.class,
                                          CLHNode.class, "tail");

  public void lock() {
    CLHNode node = new CLHNode();
    LOCAL.set(node);
    CLHNode preNode = UPDATER.getAndSet(this, node);
    if (preNode != null) {
      preNode.isLocked = Thread.currentThread();
      LockSupport.park(this);
      preNode = null;
      LOCAL.set(node);
    }
  }

  public void unlock() {
    CLHNode node = LOCAL.get();
    if (!UPDATER.compareAndSet(this, node, null)) {
      System.out.println("unlock\t" + node.isLocked.getName());
      LockSupport.unpark(node.isLocked);
    }
    node = null;
  }
}


ここではLockSupportを使いました.unpark()のブロックロック.この例はCLHロックを修正したものである.
ブロックロックの利点は、ブロックされたスレッドがcpu時間を占有しないことであり、CPu占有率が高すぎることはないが、スピンロックよりも進入時間および回復時間がやや遅いことである.
競合が激しい場合、ブロッキングロックの性能はスピンロックよりも明らかに高い.
理想的な状況は;スレッド競合が激しくない場合はスピンロック,競合が激しい場合はロック,ブロックロックを用いる.
(全文完了)