首页 > 开发 > Java > 正文

详解tryAcquire()、addWaiter()、acquireQueued()

2024-07-14 08:43:38
字体:
来源:转载
供稿:网友

本文实例为大家分享了tryAcquire()、addWaiter()、acquireQueued()的用法 ,供大家参考,具体内容如下

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就执行上面提到的lock方法的前半部分,通过CAS操作将state的值从0变为1,否则判断当前线程是否为exclusiveOwnerThread,然后把state++,也就是重入锁的体现,我们注意前半部分是通过CAS来保证同步,后半部分并没有同步的体现,原因是:后半部分是线程重入,再次获得锁时才触发的操作,此时当前线程拥有锁,所以对ReentrantLock的属性操作是无需加锁的。如果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;  }

这个方法的注释:创建一个入队node为当前线程,Node.EXCLUSIVE 是独占锁, Node.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结点。
插入节点后,调用acquireQueued()进行阻塞

acquireQueued()

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)操作,如果成功就返回,否则就执行shouldParkAfterFailedAcquire、parkAndCheckInterrupt来达到阻塞效果;

以上所述是小编给大家介绍的tryAcquire()、addWaiter()、acquireQueued()的用法详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对VeVb武林网网站的支持!


注:相关教程知识阅读请移步到JAVA教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表