除了内置锁(synchronized)外,java AQS(AbstractQueuedSynchronizer)同步器几乎是所有同步容器,同步工具类的基础。ReentrantLock、ReentrantReadWriteLock就是通过内部类继承并实现AQS的接口来实现相关功能的。

  查看AQS的源码,包含以下几个内容:

  • Node数据结构定义,用于存放被阻塞(自旋或者挂起)的线程信息,或者存放等待condition的线程,通过标记区别,共用统一数据结构
  • node队列通用操作,包括队列操作和release操作(释放资源),node队列扩展于CLH队列,
  • 各种acquire操作(获取资源)的通用方法
  • 暴露的方法,包括tryAcquire/tryRelease等非阻塞接口方法,以及acquire/release等阻塞方法
  • 队列检查方法,包括队列中是否还有node、线程是否在队列中等
  • Condition相关数据结构以及方法
  • node节点字段以及同步器字段field的CAS辅助方法,用于实现原子CAS操作

  Node节点的数据结构如下所示:

  1. static final class Node {
  2. /** Marker to indicate a node is waiting in shared mode */
  3. // 非独占
  4. static final Node SHARED = new Node();
  5. /** Marker to indicate a node is waiting in exclusive mode */
  6. // 独占
  7. static final Node EXCLUSIVE = null;
  8.  
  9. /** waitStatus value to indicate thread has cancelled */
  10. // 线程已取消
  11. static final int CANCELLED = 1;
  12. /** waitStatus value to indicate successor's thread needs unparking */
  13. // 后续节点线程需要调度
  14. static final int SIGNAL = -1;
  15. /** waitStatus value to indicate thread is waiting on condition */
  16. // 线程等待某一条件
  17. static final int CONDITION = -2;
  18. /**
  19. * waitStatus value to indicate the next acquireShared should
  20. * unconditionally propagate
  21. */
  22. // 下次acquireShared无条件传递
  23. static final int PROPAGATE = -3;
  24.  
  25. /**
  26. * Status field, taking on only the values:
  27. * SIGNAL: The successor of this node is (or will soon be)
  28. * blocked (via park), so the current node must
  29. * unpark its successor when it releases or
  30. * cancels. To avoid races, acquire methods must
  31. * first indicate they need a signal,
  32. * then retry the atomic acquire, and then,
  33. * on failure, block.
  34. * CANCELLED: This node is cancelled due to timeout or interrupt.
  35. * Nodes never leave this state. In particular,
  36. * a thread with cancelled node never again blocks.
  37. * CONDITION: This node is currently on a condition queue.
  38. * It will not be used as a sync queue node
  39. * until transferred, at which time the status
  40. * will be set to 0. (Use of this value here has
  41. * nothing to do with the other uses of the
  42. * field, but simplifies mechanics.)
  43. * PROPAGATE: A releaseShared should be propagated to other
  44. * nodes. This is set (for head node only) in
  45. * doReleaseShared to ensure propagation
  46. * continues, even if other operations have
  47. * since intervened.
  48. * 0: None of the above
  49. *
  50. * The values are arranged numerically to simplify use.
  51. * Non-negative values mean that a node doesn't need to
  52. * signal. So, most code doesn't need to check for particular
  53. * values, just for sign.
  54. *
  55. * The field is initialized to 0 for normal sync nodes, and
  56. * CONDITION for condition nodes. It is modified using CAS
  57. * (or when possible, unconditional volatile writes).
  58. */
  59. volatile int waitStatus;
  60.  
  61. /**
  62. * Link to predecessor node that current node/thread relies on
  63. * for checking waitStatus. Assigned during enqueing, and nulled
  64. * out (for sake of GC) only upon dequeuing. Also, upon
  65. * cancellation of a predecessor, we short-circuit while
  66. * finding a non-cancelled one, which will always exist
  67. * because the head node is never cancelled: A node becomes
  68. * head only as a result of successful acquire. A
  69. * cancelled thread never succeeds in acquiring, and a thread only
  70. * cancels itself, not any other node.
  71. */
  72. volatile Node prev;
  73.  
  74. /**
  75. * Link to the successor node that the current node/thread
  76. * unparks upon release. Assigned during enqueuing, adjusted
  77. * when bypassing cancelled predecessors, and nulled out (for
  78. * sake of GC) when dequeued. The enq operation does not
  79. * assign next field of a predecessor until after attachment,
  80. * so seeing a null next field does not necessarily mean that
  81. * node is at end of queue. However, if a next field appears
  82. * to be null, we can scan prev's from the tail to
  83. * double-check. The next field of cancelled nodes is set to
  84. * point to the node itself instead of null, to make life
  85. * easier for isOnSyncQueue.
  86. */
  87. volatile Node next;
  88.  
  89. /**
  90. * The thread that enqueued this node. Initialized on
  91. * construction and nulled out after use.
  92. */
  93. volatile Thread thread;
  94.  
  95. /**
  96. * Link to next node waiting on condition, or the special
  97. * value SHARED. Because condition queues are accessed only
  98. * when holding in exclusive mode, we just need a simple
  99. * linked queue to hold nodes while they are waiting on
  100. * conditions. They are then transferred to the queue to
  101. * re-acquire. And because conditions can only be exclusive,
  102. * we save a field by using special value to indicate shared
  103. * mode.
  104. */
  105. Node nextWaiter;
  106.  
  107. /**
  108. * Returns true if node is waiting in shared mode
  109. */
  110. final boolean isShared() {
  111. return nextWaiter == SHARED;
  112. }
  113.  
  114. /**
  115. * Returns previous node, or throws NullPointerException if null.
  116. * Use when predecessor cannot be null. The null check could
  117. * be elided, but is present to help the VM.
  118. *
  119. * @return the predecessor of this node
  120. */
  121. final Node predecessor() throws NullPointerException {
  122. Node p = prev;
  123. if (p == null)
  124. throw new NullPointerException();
  125. else
  126. return p;
  127. }
  128.  
  129. Node() { // Used to establish initial head or SHARED marker
  130. }
  131.  
  132. Node(Thread thread, Node mode) { // Used by addWaiter
  133. this.nextWaiter = mode;
  134. this.thread = thread;
  135. }
  136.  
  137. Node(Thread thread, int waitStatus) { // Used by Condition
  138. this.waitStatus = waitStatus;
  139. this.thread = thread;
  140. }
  141. }

java AQS(AbstractQueuedSynchronizer)同步器详解的更多相关文章

  1. java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock

    原文:java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock 锁 锁是用来控制多个线程访问共享资源的方式,java中可以使用synch ...

  2. Java 8 Stream API详解--转

    原文地址:http://blog.csdn.net/chszs/article/details/47038607 Java 8 Stream API详解 一.Stream API介绍 Java8引入了 ...

  3. java反射机制深入详解

    java反射机制深入详解  转自:http://www.cnblogs.com/hxsyl/archive/2013/03/23/2977593.html 一.概念 反射就是把Java的各种成分映射成 ...

  4. 国际化,java.util.ResourceBundle使用详解

    java.util.ResourceBundle使用详解   一.认识国际化资源文件   这个类提供软件国际化的捷径.通过此类,可以使您所编写的程序可以:          轻松地本地化或翻译成不同的 ...

  5. java之StringBuffer类详解

    StringBuffer 线程安全的可变字符序列. StringBuffer源码分析(JDK1.6): public final class StringBuffer extends Abstract ...

  6. java.util.ResourceBundle使用详解

    java.util.ResourceBundle使用详解   一.认识国际化资源文件   这个类提供软件国际化的捷径.通过此类,可以使您所编写的程序可以:          轻松地本地化或翻译成不同的 ...

  7. java之AbstractStringBuilder类详解

    目录 AbstractStringBuilder类 字段 构造器 方法   public abstract String toString() 扩充容量 void  expandCapacity(in ...

  8. java之StringBuilder类详解

    StringBuilder 非线程安全的可变字符序列 .该类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍).如果可能,建议优先采用该类,因为在 ...

  9. java.util.ResourceBundle使用详解(转)

    java.util.ResourceBundle使用详解   一.认识国际化资源文件   这个类提供软件国际化的捷径.通过此类,可以使您所编写的程序可以:          轻松地本地化或翻译成不同的 ...

  10. java web.xml配置详解(转)

    源出处:java web.xml配置详解 1.常规配置:每一个站的WEB-INF下都有一个web.xml的设定文件,它提供了我们站台的配置设定. web.xml定义: .站台的名称和说明 .针对环境参 ...

随机推荐

  1. 使用pynlpir增强jieba分词的准确度

    在使用jieba分词时,发现分词准确度不高.特别是一些专业词汇,比如堡垒机,只能分出堡垒,并不能分出堡垒机.这样导致的问题是很多时候检索并不准确. 经过对比测试,发现nlpir进行分词效果更好.但是n ...

  2. bzoj 4767 两双手 - 动态规划 - 容斥原理

    题目传送门 传送门I 传送门II 题目大意 一个无限大的棋盘上有一只马,设马在某个时刻的位置为$(x, y)$, 每次移动可以将马移动到$(x + A_x, y + A_y)$或者$(x + B_x, ...

  3. CEF JS实现获取剪贴板图片的DataURL

    转载:https://www.deanhan.cn/js-paste-upload.html 转载:https://segmentfault.com/a/1190000002915597 转载:htt ...

  4. [java]第一个程序

    HelloWorld 主函数 学习一门语言第一部分就是学习主函数,Java的主函数是main函数有如下形式: public class HelloWorld{ public static void m ...

  5. ComponentOne 2019V1:全面支持 Visual Studio 2019

    ComponentOne Enterprise 2019V1已经正式发布,本次更新的最大亮点就是 ComponentOne 控件全面支持 Visual Studio 2019. 作为一款专注于企业应用 ...

  6. js随机数的取整

  7. scipy插值与拟合

    原文链接:https://zhuanlan.zhihu.com/p/28149195 1.最小二乘拟合 实例1 import numpy as np import matplotlib.pyplot ...

  8. IOS高级开发之多线程(四)NSOperation

    1.什么是NSOperation,NSOperationQueue? NSOperation是一个抽象的基类,表示一个独立的计算单元,可以为子类提供有用且线程安全的建立状态,优先级,依赖和取消等操作. ...

  9. linux文件 特殊权限的使用

    http://www.iqiyi.com/a_19rrh3tui5.html 1.说明 i属性不能修改 a只能追加在6以后 [root@xuegod63 ~]# chattr +i a.txt [ro ...

  10. 《R语言入门与实践》第四章:R 的记号体系

    这一章节将如何对 R 对象中的值进行选取,R 的符号规则有两种方式进行查询: 第一种记号体系:索引查询索引语法:deck[ , ](使用中括号)其中[ , ] 为索引,其中含有两个索引参数,用 &qu ...