tryAcquire()、addWaiter()、acquire Qued()を詳細に説明する。


本論文の例ではtryAcquire()、addWaiter()、acquire Qued()の使い方を共有しています。参考にしてください。具体的な内容は以下の通りです。
tryAcquire()

final boolean nonfairTryAcquire(int acquires) {
      final Thread current = Thread.currentThread();
      int c = getState();
      if (c == 0) {
        if (compareAndSetState(0, acquires)) {
          setExclusiveOwnerThread(current);
          return true;
        }
      }
      else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0) // overflow
          throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
      }
      return false;
    }
まず、stateが0かどうかを判断し、0であれば上記のロック方法の前半部分を実行し、CAS操作によってstateの値を0から1に変更します。そうでなければ、現在のスレッドがexclusive Owner Threadかどうかを判断し、state+、つまり再入力ロックの体現を行います。前半部分はCASによって同期を保証しています。後半部分は同期されていません。後半部分はスレッド再入で、再びロックを獲得した時にトリガされる操作で、現在のスレッドはロックされているので、Rentrant Lockの属性操作にロックは不要です。tryAcquire()の取得に失敗した場合、addWaiter()を実行して待ち行列に独占モードを追加するノード。
addWaiter()

/**
   * Creates and enqueues node for current thread and given mode.
   *
   * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
   * @return the new node
   */
  private Node addWaiter(Node mode) {
    Node node = new Node(Thread.currentThread(), mode);
    // Try the fast path of enq; backup to full enq on failure
    Node pred = tail;
    if (pred != null) {
      node.prev = pred;
      if (compareAndSetTail(pred, node)) {
        pred.next = node;
        return node;
      }
    }
    enq(node);
    return node;
  }
この方法のコメント:現在スレッドを作成します。ノード・EXCLUSIVEは独占ロックです。ノード・SHAREDは共有ロックです。
先に待ち行列のtailノードpredを見つけます。predなら!=nullは、現在スレッドをpredの後に追加して待ち行列に入ります。もしtailノードが存在しないなら、enq()を実行します。

private Node enq(final Node node) {
    for (;;) {
      Node t = tail;
      if (t == null) { // Must initialize
        if (compareAndSetHead(new Node()))
          tail = head;
      } else {
        node.prev = t;
        if (compareAndSetTail(t, node)) {
          t.next = node;
          return t;
        }
      }
    }
  }
ここでループを行いましたが、この時点でtailが存在すると、同じステップの追加チームの最後の動作が実行されます。まだ存在しない場合は、現在のスレッドをhead結点とします。
ノードを挿入した後、acquire Queuedを呼び出してブロックします。
acquire Queued()

final boolean acquireQueued(final Node node, int arg) {
    boolean failed = true;
    try {
      boolean interrupted = false;
      for (;;) {
        final Node p = node.predecessor();
        if (p == head && tryAcquire(arg)) {
          setHead(node);
          p.next = null; // help GC
          failed = false;
          return interrupted;
        }
        if (shouldParkAfterFailedAcquire(p, node) &&
          parkAndCheckInterrupt())
          interrupted = true;
      }
    } finally {
      if (failed)
        cancelAcquire(node);
    }
  }
先に現在のノードの前のノードpを取得し、pがheadであればもう一度tryAcquire(arg)操作を行い、成功すれば戻ります。そうでなければShuldParkAfterFaileAcquire、parkAndCheckInterruptを実行してブロック効果を達成します。
以上は小编が绍介したtryAcquire()、addWaiter()、acquire Queued()の使い方を详しく整理していますので、皆さんに助けてほしいです。もし何かご质问があれば、メッセージをください。ここでも私たちのサイトを応援してくれてありがとうございます。