AQS重要性
Java------> JVM
JUC-------> AQS
2、前置知识
公平锁和非公平锁
可重入锁
自旋思想
LockSupport
数据结构之双向链表
设计模式之模板设计模式
3、理论知识
3.1、是什么
字面意思
抽象的队列同步器
是用来实现锁或者其它同步器组件的公共基础部分的抽象实现,
是
重
量
级
基
础
框
架
及
整
个
J
U
C
体
系
的
基
石
,
主
要
用
子
解
决
锁
分
配
给
"
谁
"
的
问
题
\color{red}重量级基础框架及整个JUC体系的基石,主要用子解决锁分配给"谁"的问题
重量级基础框架及整个JUC体系的基石,主要用子解决锁分配给"谁"的问题
官网解释
整体就是一个抽象的FIFO 队 列 \color{red}队列 队列来完成资源获取线程的排队工作,并通过一个 i n t 类 变 量 \color{red}int类变量 int类变量表示持有锁的状态
3.2、AQS为什么是JUC内容中最重要的 基 石 \color{red}基石 基石
ReentranLock
CountDownLatch
ReentrantReadWriteLock
Semaphore
进一步理解锁和同步器的关系
锁,面向锁的使用者
- 定义了程序员和l锁交互的使用层API,隐藏了实现细节,你调用即可。
同步器,面向锁的实现者
- Java并发大神DougLee,提出统一规范并简化了锁的实现,
将
其
抽
象
出
来
\color{red}将其抽象出来
将其抽象出来
屏蔽了同步状态管理、同步队列的管理和维护、阻塞线程排队和通知、唤醒机制等, - 是一切锁和同步组件立现.的------- 公 共 基 础 部 分 \color{red}公共基础部分 公共基础部分
3.2、能干嘛
加
锁
会
导
致
阻
塞
\color{red}加锁会导致阻塞
加锁会导致阻塞
有阻塞就需要排队,实现排队必然需要队列
解释说明
抢到资源的线程直接使用处理业务,抢不到资源的必然涉及一种 排 队 等 候 机 制 \color{red}排队等候机制 排队等候机制。抢占资源失败的线程继续去等待(类似银行业务办理窗口都满了,暂时没有受理窗口的顾客只能去 候 客 区 排 队 等 候 \color{red}候客区排队等候 候客区排队等候),但等候线程仍然保留获取锁的可能且获取锁流程仍在继续(候客区的顾客也在等着叫号,轮到再去受理窗口办理业务)。
既然说到了 排 队 等 候 机 制 \color{red}排队等候机制 排队等候机制,那么就一定会有某种队列形成,这样的队列是什么数据结构呢?
如果共享资源被占用, 就 需 要 一 定 的 阻 塞 等 待 唤 醒 机 制 来 保 证 锁 分 配 。 \color{blue}就需要一定的阻塞等待唤醒机制来保证锁分配。 就需要一定的阻塞等待唤醒机制来保证锁分配。
这个机制主要用的是CLH队列的变体实现的,将暂时获取不到锁的线程加入到队列中,这个队列就是AQS同步队列的抽象表现。
它将要请求共享资源的线程及自身的等待状态封装成队列的结点对象( N o d e \color{red}Node Node),
通过CAS、自旋以及LockSupport.park()的方式,维护state变量的状态,使并发达到同步的效果。
源码查看
源码说明
AQS
使用一个volatile
的int
类型的成员变量来表示同步状态,
通过内置的FIFO
队列来完成资源获取的排队工作
将每条要去抢占资源的线程及自身的等待状态封装成一个Node
节点来实现锁的分配,
通过CAS
完成对State
值的修改。
3.3、小总结
CLH: Craig、Landin and Hagersten队列,是个单向链表,AQS中的队列是CLH变体的虚拟双向队列(FIFO)
4、AQS内部体系架构
4.1、AQS自身
4.1.1、 A Q S 的 i n t 变 量 \color{red}AQS的int变量 AQS的int变量
AQS的同步状态State成员变量
银行办理业务的受理窗口状态
-
零就是没人,自由状态可以办理
-
大于等于1,有人占用窗口,等着去
4.1.2、AQS的CLH队列
银行候客区的等待客户
4.1.3、小总结
有 阻 塞 就 需 要 排 队 \color{red}有阻塞就需要排队 有阻塞就需要排队,
实现排队必然需要队列state变量+CLH双端队列
4.2、内部类Node(Node类在AQS类的内部)
4.2.1、 N o d e 的 i n t 变 量 \color{red}Node的int变量 Node的int变量
Node的等待状态waitState成员变量
volatile int waitStatus
说人话
等候区其它顾客(其它线程)的等待状态
队列中每个排队的个体就是一个Node
4.2.2、Node此类的讲解
.4.2.2.1、内部结构
static final class Node {
//共享方式
static final Node SHARED = new Node();
//独占方式
static final Node EXCLUSIVE = null;
//线程被取消了
static final int CANCELLED = 1;
//后继线程需要唤醒
static final int SIGNAL = -1;
//表示节点在等待队列中,节点线程等待唤醒
static final int CONDITION = -2;
//共享式同步状态获取将会无条件的传播下去,在 SHARED 情况下,该字段才会使用
static final int PROPAGATE = -3;//传播
//初始为0,状态是上面的几种,当前节点(线程)在队列中的状态
volatile int waitStatus;
//前置节点
volatile Node prev;
//后继节点
volatile Node next;
/**
* The thread that enqueued this node. Initialized on
* construction and nulled out after use.
*/
volatile Thread thread;
//下一个处于 condition 状态的节点
Node nextWaiter;
/**
* Returns true if node is waiting in shared mode.
*/
final boolean isShared() {
return nextWaiter == SHARED;
}
/**
* Returns previous node, or throws NullPointerException if null.
* Use when predecessor cannot be null. The null check could
* be elided, but is present to help the VM.
*
* @return the predecessor of this node
*/
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
Node() { // Used to establish initial head or SHARED marker
}
Node(Thread thread, Node mode) { // Used by addWaiter
this.nextWaiter = mode;
this.thread = thread;
}
Node(Thread thread, int waitStatus) { // Used by Condition
this.waitStatus = waitStatus;
this.thread = thread;
}
}
4.2.2.2、属性说明!
5、AQS源码深度讲解和分析
5.1、Lock接口的实现类
基本都是通过【聚合】了一个【队列同步器】的子类完成线程访问控制的
5.2、ReentrantLock的原理
public class AqsDemo {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
}
}
public class AqsDemo {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
lock.lock();
}
}
可 以 明 显 看 出 公 平 锁 与 非 公 平 锁 的 l o c k ( ) 方 法 唯 一 的 区 别 就 在 于 公 平 锁 在 获 取 同 步 状 态 时 多 了 一 个 限 制 条 件 : \color{red}可以明显看出公平锁与非公平锁的lock()方法唯一的区别就在于公平锁在获取同步状态时多了一个限制条件: 可以明显看出公平锁与非公平锁的lock()方法唯一的区别就在于公平锁在获取同步状态时多了一个限制条件:
h a s Q u e u e d P r e d e c e s s o r s ( ) \color{red}hasQueuedPredecessors() hasQueuedPredecessors()
h a s Q u e u e d P r e d e c e s s o r s 是 公 平 锁 加 锁 时 判 断 等 待 队 列 中 是 否 存 在 有 效 节 点 的 方 法 \color{red}hasQueuedPredecessors是公平锁加锁时判断等待队列中是否存在有效节点的方法 hasQueuedPredecessors是公平锁加锁时判断等待队列中是否存在有效节点的方法
5.3、从lock方法开始看公平与非公平
对比公平锁和非公平锁的tryAcquire() 方法的实现代码,
其实差别就在于非公平锁获取锁时比公平锁中少了一个判断 ! h a s Q u e u e d P r e d e c e s s o r s ( ) \color{red} !hasQueuedPredecessors() !hasQueuedPredecessors()
hasQueuedPredecessors() 中判断了是否需要排队,导致公平锁和非公平锁的差异如下:
公 平 锁 \color{blue}公平锁 公平锁:
- 公平锁讲究先来先到,线程在获取锁时,如果这个锁的等待队列中已经有线程在等待,那么当前线程就会进入等待队列中;
非 公 平 锁 \color{blue}非公平锁 非公平锁:
- 不管是否有等待队列,如果可以获取锁,则立刻占有锁对象。
- 也就是说队列的第一个排队线程苏醒后,不一定就是排头的这个线程获得锁,它还是需要参加竞争锁〈存在线程竞争的情况下),后来的线程可能 不 讲 武 德 \color{red}不讲武德 不讲武德插队夺锁了。
非公平锁没有竞争成功则会去加入到请求队列中
//ReetrantLock
public void lock() {
sync.lock();
}
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
/**
* Performs {@link Lock#lock}. The main reason for subclassing
* is to allow fast path for nonfair version.
*/
abstract void lock();//由 FairSync 与 NoFairSync 去实现
//...
}
static final class NonfairSync extends Sync { //Sync的子类
private static final long serialVersionUID = 7316153563782823691L;
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
if (compareAndSetState(0, 1))//竞争成功
setExclusiveOwnerThread(Thread.currentThread()); //设置为独享线程
else
acquire(1); //竞争失败,请求
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);//非公平锁
}
}
static final class FairSync extends Sync { //Sync的子类
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);//请求
}
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
5.4、以非公平锁为例,lock()
5.4.1、 l o c k ( ) \color{red}lock() lock()
static final class NonfairSync extends Sync { //Sync的子类
private static final long serialVersionUID = 7316153563782823691L;
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
if (compareAndSetState(0, 1))//尝试进行比较交换当前状态
setExclusiveOwnerThread(Thread.currentThread()); //设置为独享线程
else
acquire(1); //竞争失败,请求后续3大步操作
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
compareAndSetState(0, acquires)
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
//...
protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
}
setExclusiveOwnerThread(current);
//ReentrantLock 是其子类
public abstract class AbstractOwnableSynchronizer
implements java.io.Serializable {
//...
/**
* The current owner of exclusive mode synchronization.
*/
private transient Thread exclusiveOwnerThread;
protected final void setExclusiveOwnerThread(Thread thread) {
exclusiveOwnerThread = thread;
}
//...
}
5.4.2、acquire()
源码与3大流程走向
AbstractQueuedSynchronizer
5.4.3、 ! t r y A c q u i r e \color{blue}!tryAcquire !tryAcquire(先再次进行尝试获取锁)
!tryAcquire(arg)
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);
}
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();// 若其他线程进来,此时c 是 1,直接返回false
if (c == 0) { //可能当前线程释放了锁,即状态位 c = 0,所以
if (// 公平锁有这个 !hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) { //如果是当前同一个线程
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;//返回false,继续推进条件,走下一个方法
}
}
! h a s Q u e u e d P r e d e c e s s o r s ( ) \color{red}!hasQueuedPredecessors() !hasQueuedPredecessors()
其中公平锁对应的 !hasQueuedPredecessors() &&
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
/*
1.队列不为空
头节点不等于tail节点
=>
1.[s = 头结点的下一个节点为空(队列只有一个节点=1) || s不等于当前线程(队列元素>1)]
=> 返回true,!hasQueuedPredecessors() = false ,直接返回false,
进入addWaiter方法(再次竞争或入队)
tryAcquire()=false,排队
2. 队列元素>1。头节点的下一个节点不为null。s!=null && s==当前线程
即:是当前队列的下一个节点的线程
去CAS交换state(状态): compareAndSetState(0, acquires),
成功:
调用setExclusiveOwnerThread(current); 设置为所持有线程
整个tryAcquire()=true,表示获取锁成功,
失败
整个tryAcquire()=false,
排队
2.队列为空,直接返回 false,表示无需排队,
去竞争锁 compareAndSetState(0, acquires),
成功:
调用setExclusiveOwnerThread(current); 设置为所持有线程
整个tryAcquire()=true,表示获取锁成功,
失败
整个tryAcquire()=false,
排队
*/
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
5.4.4、 a d d W a i t e r \color{blue}addWaiter addWaiter(再次竞争失败,封装入队)
addWaiter(Node.EXCLUSIVE)
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
//...
// mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
//为当前线程和给定模式创建和排队节点。
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); //将队列头设置为节点,队列开始为空,或者上面cas入队失败,进入enq循环入队
return node;
}
//...
//将队列头设置为节点,从而取消排队,尾插法
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize 第一次队列为空
//虚拟头节点 Thread = null , waitStatus = 0
if (compareAndSetHead(new Node()))
tail = head;
} else { //队列不为空,尾插法插入节点
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
}
双向链表中, 第 一 个 节 点 为 虚 节 点 ( 也 叫 哨 兵 节 点 , 虚 拟 头 节 点 ) \color{red}第一个节点为虚节点(也叫哨兵节点,虚拟头节点) 第一个节点为虚节点(也叫哨兵节点,虚拟头节点),其实并不存储任何信息,只是占位。真正的第一个有数据的节点,是从第二个节点开始的。
5.4.5、 a c q u i r e Q u e u e d \color{blue}acquireQueued acquireQueued(阻塞和释放)
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
5.4.5.1、阻塞
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
//...
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();//获得前置节点
//会有一次CAS,尝试获取锁(tryAcquire(arg)),获取不到才会 park,阻塞自己
if (p == head && tryAcquire(arg)) {//前提若p是头节点(虚拟头节点) && 抢占锁成功
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed) //失败情况
cancelAcquire(node);
}
}
//...
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
//只有waitState = -1 时候(等待被占用的资源释放),才会返回true
if (ws == Node.SIGNAL)
/*
* This node has already set status asking a release
* to signal it, so it can safely park.
* 此节点已设置状态,要求释放以发出信号,以便它可以安全地停放。
*/
return true;
// ws 大于0说明是CANCELLED状态
if (ws > 0) {
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
* 循环判断前驱节点的前驱节点是否也为CANCELLED状态,忽略该状态的节点,重新连接队列
*/
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {//一开始新建节点状态为0。
/*
* waitStatus must be 0 or PROPAGATE. Indicate that we
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
*
* 将当前节点的前驱节点设置为设置为SIGNAL状态,用于后续唤醒操作
* 程序第一次执行到这返回为false,还会进行外层第二次循环,最终从代码第7行返回
*/
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);//设置waitState为信号,-1
}
return false;
}
}
B
第一次进入进入shouldParkAfterFailedAcquire(p, node)
节点waitState = 0
,然后设置 compareAndSetWaitStatus(pred, ws, Node.SIGNAL)
;
//设置P(head) waitState
为信号,-1
后,
返回方法继续进行循环,再次进入shouldParkAfterFailedAcquire(p, node)
方法返回,
此时waitState = -1 ,return true
,然后阻塞当前B线程
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
//...
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)) {//前提若p是头节点(虚拟头节点) && 抢占锁成功
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) && //true,waitState = -1
parkAndCheckInterrupt())//阻塞当前线程
interrupted = true;
}
} finally {
if (failed) //失败情况
cancelAcquire(node);
}
}
//....
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);//阻塞当前线程.
return Thread.interrupted();
}
}
此时C
线程进来了,会进入shouldParkAfterFailedAcquire(p, node)
将 B
的waitState
改为 - 1
返回方法继续进行循环,再次进入shouldParkAfterFailedAcquire(p, node)
方法返回,
此时P(B)
的 waitState = -1 ,return true
,然后阻塞当前C线程
就是后来的线程会将前面队列的线程waitState修改为 -1,然后阻塞当前线程
5.5、unlock()
sync.release(1) -> tryRelease(arg) -> unparkSuccessor
5.5.1、sync.release(1)
public class ReentrantLock implements Lock, java.io.Serializable {
//...
public void unlock() {
sync.release(1);
}
}
A线程解锁,尝试释放tryRelease
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
//...
public final boolean release(int arg) {
if (tryRelease(arg)) {//尝试释放,此时为若 A 为 true
Node h = head;//获取头结点
if (h != null && h.waitStatus != 0) //不为空 并且不为 0 (此时为 -1)
unparkSuccessor(h);
return true;
}
return false;
}
//...
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
}
5.5.2、tryRelease(arg)
此时 state = 1
,如果 c = 0
,,将独占线程置空 ,重新设置状态为 c
,返回 true
public class ReentrantLock implements Lock, java.io.Serializable {
//...
protected final boolean tryRelease(int releases) {
int c = getState() - releases; //1 - 1 = 0
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
//...
}
5.5.3、unparkSuccessor
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
//...
public final boolean release(int arg) {
if (tryRelease(arg)) {//尝试释放,此时为若 A 为 true
Node h = head;//获取头结点
if (h != null && h.waitStatus != 0) //不为空 并且不为 0 (此时为 -1)
unparkSuccessor(h);//head.next 解锁
return true;
}
return false;
}
//...
private void unparkSuccessor(Node node) {
/*
* If status is negative (i.e., possibly needing signal) try
* to clear in anticipation of signalling. It is OK if this
* fails or if status is changed by waiting thread.
*/
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
/*
* Thread to unpark is held in successor, which is normally
* just the next node. But if cancelled or apparently null,
* traverse backwards from tail to find the actual
* non-cancelled successor.
*/
Node s = node.next; // 获取结点(传入的是head)的下一个节点(此时为node.next = B线程)
if (s == null || s.waitStatus > 0) {//头结点的下一个节点为null,此时,头尾相连
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread); // (B线程唤醒)
}
}
5.5.4、唤醒后事件
此时B
被唤醒了。重新循环,此时p == head
,
B
线程试图去tryAcquire(arg)
,即试图抢占锁,
- 因为我们用的是非公平锁,
A
线程可能释放后还会参与竞争
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
//...
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)) {//前提若p是头节点(虚拟头节点) && 抢占锁成功
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt()) // 此时返会false
interrupted = true;
}
} finally {
if (failed) //失败情况
cancelAcquire(node);
}
}
//....
private final boolean parkAndCheckInterrupt() {
//阻塞当前线程(若为B,),此时B被唤醒了(LockSupport.unpark(s.thread))
LockSupport.park(this);
//返回当前线程是否被设置中断标志位(true/false),并重置中断标志位false
return Thread.interrupted();//返回 false
}
}
B
线程试图去tryAcquire(arg)
,即试图抢占锁,
- 因为我们用的是非公平锁,A线程可能释放后还会参与竞争
public class ReentrantLock implements Lock, java.io.Serializable {
//...
abstract static class Sync extends AbstractQueuedSynchronizer {
//....
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {//若B线程进来,此时c = 0(A释放了锁)
//尝试CAS
if (compareAndSetState(0, acquires)) {
//设置B为独占线程
setExclusiveOwnerThread(current);
//返回true
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;
}
}
}
假设B
线程 tryAcquire(arg)
,即试图抢占锁成功 返回true
此时此时B
抢占锁成功,进入if
体
重新设置B
为 头结点,删除之前的头结点,返回 false
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
//...
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
//此时A是head节点,且B抢占锁成功
if (p == head && tryAcquire(arg)) {
//重新设置头结点(这里B设置为 头结点)
/*
private void setHead(Node node) {
head = node;
node.thread = null;
node.prev = null;
}
*/
setHead(node);
p.next = null; // help GC ,删除前一个节点P
//没有失败
failed = false;
//返回 true (因为 B线程阻塞了之后 再 被唤醒了)
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
//...
}
5.6、若线程不想等待了(异常)
若其中某个或者多个线程不想等待了,出队
5.6.1、队尾节点不等待
可能因为某种异常打断了,failed
没有改为 false
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
//...
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);
}
}
//...
}
此时 出现了线程异常 ,(不想等待), 进入 cancelAcquire(node)
;
//.....
private void cancelAcquire(Node node) { //假设5号节点为队尾,5号线程出队
// Ignore if node doesn't exist
if (node == null)
return;
//将当前节点(5号)的线程置空
node.thread = null;
// 获取当前节点的前一个节点线程 (pred = 4 号节点)
Node pred = node.prev;
// waitStatus > 0 只有一种情况, CANCELLEND = 1,表示线程获取锁的请求已经取消了
// 若 4号节点已经取消了(当前4号不取消)
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
// predNext is the apparent node to unsplice. CASes below will
// fail if not, in which case, we lost race vs another cancel
// or signal, so no further action is necessary.
// 前一个的节点的下一个节点,(5号节点)
Node predNext = pred.next;
// Can use unconditional write instead of CAS here.
// After this atomic step, other Nodes can skip past us.
// Before, we are free of interference from other threads.
// 将 当前节点(5号节点)的状态改为 1(取消状态)
node.waitStatus = Node.CANCELLED;
// If we are the tail, remove ourselves.
// 如果 当前节点是队尾节点,CAS 将当前节点(队尾节点)设置为前一个节点 (将5号节点设置为4号节点)
if (node == tail && compareAndSetTail(node, pred)) {
//将前一节点的下一个节点置null,就是删除下一节点(将4号节点的下一个节点5号节点置null)
compareAndSetNext(pred, predNext, null);
} else {
// If successor needs signal, try to set pred's next-link
// so it will get one. Otherwise wake it up to propagate.
int ws;
if (pred != head &&
((ws = pred.waitStatus) == Node.SIGNAL ||
(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
pred.thread != null) {
Node next = node.next;
if (next != null && next.waitStatus <= 0)
compareAndSetNext(pred, predNext, next);
} else {
unparkSuccessor(node);
}
node.next = node; // help GC
}
}
5.6.2、中间节点
假设4
号节点想取消,其前一个节点3
号节点也想取消
3,4
号都想取消
//.....
private void cancelAcquire(Node node) { //假设5号节点为队尾,5号线程出队
// Ignore if node doesn't exist
if (node == null)
return;
//将当前节点(5号)的线程置空
node.thread = null;
// 获取当前节点的前一个节点线程 (pred = 4 号节点)
Node pred = node.prev;
// waitStatus > 0 只有一种情况, CANCELLEND = 1,表示线程获取锁的请求已经取消了
// 不断向前找为取消的节点(2号节点未被取消)
// 此时即 node.prev = 2号节点
// pred = 2号节点
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
// predNext is the apparent node to unsplice. CASes below will
// fail if not, in which case, we lost race vs another cancel
// or signal, so no further action is necessary.
// (此时为2号节点)的下一个节点,(3号节点)
// predNext = 3号节点
Node predNext = pred.next;
// Can use unconditional write instead of CAS here.
// After this atomic step, other Nodes can skip past us.
// Before, we are free of interference from other threads.
// 将 当前节点()的状态改为 1(取消状态)
node.waitStatus = Node.CANCELLED;
// If we are the tail, remove ourselves.
// 4号节点不是队尾,进入else
if (node == tail && compareAndSetTail(node, pred)) {
compareAndSetNext(pred, predNext, null);
} else {
// If successor needs signal, try to set pred's next-link
// so it will get one. Otherwise wake it up to propagate.
int ws;
// pred 不是队头节点
if (pred != head &&
//pred(2号节点) = -1
((ws = pred.waitStatus) == Node.SIGNAL ||
(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
pred.thread != null) {
//next = 当前节点的下一个节点 (5号节点)
Node next = node.next;
//此时 next != null ,或者状态小于等于0 ,(5号节点)
if (next != null && next.waitStatus <= 0)
//pred = 2 , predNext = 3, next = 5
//将2号节点的下一个节点改为5号节点
compareAndSetNext(pred, predNext, next);
} else {
unparkSuccessor(node);
}
//当前节点(4号节点)的下一个节点指向自己,GC删除
node.next = node; // help GC
}
}