AQS:核心方法
acquire(int arg): 进入临界区,失败加入队列,park, unpark之后再次尝试进入临界区
boolean tryAcquire(int arg); 试图进入临界区;
Node addWaiter(Node): 将该线程添加至同步队列尾节点(双向链表队列)
+ 当前线程构建成 新Node节点;
+ 新Node CAS 至 tail;
+ (CAS失败) enq(Node);
Node enq(Node)
+ 若队列为空,初始化 new Node() 为 head.
+ for循环直至成功 => 新Node CAS 至 tail.
boolean acquireQueued(final Node node, int arg):
+ for循环:直到当前节点前置节点为Head才可出队列;
+ 若当前节点的 前继节点是Head,说明当前节点为第一个节点可出队列;
+ 若不是,则shouldParkAfterFailedAcquire将前一个节点设置为 Node.SIGNAL,进入LockSupport.park(this)
-
通过上述流程,需注意:
- Head节点是空节点;
- 前置节点的prev.waitStatus表示当前节点的状态(<=0为有效)
- LockSupport.park 之前,会从队尾检查移除已取消的节点;
void unparkSuccessor(Node node):从同步队列取出Node,unpark(node.thread)
+ 取出第一个有效节点,进行unpark节点的thread
+ 其中若第一个节点不是有效,会将尾节点一直向Head节点查找;
AQS:钩子方法:(临界区维护state 线程同步状态)
-
boolean tryAcquire(int arg)
- 需要检查是否符合进入临界区条件 boolean tryRelease(int arg)
- 恢复临界区条件,使后续线程可进入临界区 int tryAcquireShared(int arg)
- 同tryAcquire(int arg)语义,返回值是int boolean tryReleaseShared(int arg)
- 同tryRelease(int arg) 语义
AQS:工具方法
-
进入临界区
acquire(int arg)
acquireInterruptibly(int arg)
acquireShared(int arg)
acquireSharedInterruptibly(int arg)
tryAcquireNanos(int arg, long nanosTimeout)
tryAcquireSharedNanos(int arg, long nanosTimeout) -
退出临界区
release(int arg)
releaseShared(int arg)