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

 更新时间:2019年03月13日 15:51:12   作者:胖虎。。  
这篇文章主要tryAcquire()、addWaiter()、acquireQueued()的用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

本文实例为大家分享了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()的用法详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

相关文章

  • TransactionSynchronization的invokeAfterCompletion事务源码解析

    TransactionSynchronization的invokeAfterCompletion事务源码解析

    这篇文章主要为大家介绍了TransactionSynchronization的invokeAfterCompletion事务源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • Springboot实现人脸识别与WebSocket长连接的实现代码

    Springboot实现人脸识别与WebSocket长连接的实现代码

    这篇文章主要介绍了Springboot实现人脸识别与WebSocket长连接的实现,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2023-11-11
  • Java中synchronized的几种使用方法

    Java中synchronized的几种使用方法

    本文主要介绍了Java中synchronized的几种使用方法,synchronized可用于修饰普通方法、静态方法和代码块,下面详细内容介绍,需要的小伙伴可以参考一下
    2022-05-05
  • SpringBoot读取Resource下文件的4种方法

    SpringBoot读取Resource下文件的4种方法

    这篇文章主要介绍了SpringBoot读取Resource下文件的4种方法小结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • Springboot升级到2.7.2结合nacos遇到的坑及解决

    Springboot升级到2.7.2结合nacos遇到的坑及解决

    这篇文章主要介绍了Springboot升级到2.7.2结合nacos遇到的坑及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • 在Mybatis @Select注解中实现拼写动态sql

    在Mybatis @Select注解中实现拼写动态sql

    这篇文章主要介绍了在Mybatis @Select注解中实现拼写动态sql,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • hibernate框架环境搭建具体步骤(介绍)

    hibernate框架环境搭建具体步骤(介绍)

    下面小编就为大家带来一篇hibernate框架环境搭建具体步骤(介绍)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • IDEA解决Java:程序包xxxx不存在的问题

    IDEA解决Java:程序包xxxx不存在的问题

    这篇文章主要介绍了IDEA解决Java:程序包xxxx不存在的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • Spring5中SpringWebContext方法过时的解决方案

    Spring5中SpringWebContext方法过时的解决方案

    这篇文章主要介绍了Spring5中SpringWebContext方法过时的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Java汉字转拼音案例详解

    Java汉字转拼音案例详解

    这篇文章主要介绍了Java汉字转拼音案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08

最新评论