目录
1. AbstractQueuedSynchronizer 介绍
1. AbstractQueuedSynchronizer 介绍
抽象同步队列 AbstractQueuedSynchronizer ,简称 AQS,它是实现阻塞锁和其他基于先入先出(FIFO)等待队列的同步组件。
并发包中锁的底层实现(如 ReentrantLock )的底层实现就是使用 AQS 实现的。
2. AQS 内部结构
i. AQS 继承自 AbstractOwnableSynchronizer
ii. 类 ConditionObject 主要提供一种条件,由子类决定是否支持独占模式
iii. 类 Node,作为先入先出(FIFO)阻塞队列里面的每个节点
3. 状态信息 state
AQS 维持了一个单一的状态信息 state,可通过 getState()、setState(int newState)、compareAndSetState(int expect, int update) 方法来修改 state 的值。
private static final Unsafe unsafe = Unsafe.getUnsafe();
// 状态信息
private volatile int state;
// 返回当前的状态值。该操作拥有 volatile 读的内存语义
protected final int getState() {
return state;
}
//设置状态值
protected final void setState(int newState) {
state = newState;
}
// 通过 unsafe 类原子的设置同步状态值为给定的 update 值,设置成功后返回true,否则返回false
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
state 作用举例:
ReentrantLock 中,state 表示当前线程获取锁的可重入次数。
ReentrantReadWriteLock 中,state 高 16 位表示获取读锁的次数,低 16 为表示获取写锁的线程的可重入次数。
4. 内部类 Node
4.1 Node 类源码
static final class Node {
// 标记符,共享模式下的等待节点
static final Node SHARED = new Node();
// 标记符,独占模式下等待节点
static final Node EXCLUSIVE = null;
/**
* 等待状态值
* 1 表示线程已经被取消
* -1 表示一个后继节点的线程需要唤醒
* -2 表示线程等待在某种条件下
* -3 表示下一次共享式获取状态的操作应该无条件的传播
*/
static final int CANCELLED = 1;
static final int SIGNAL = -1;
static final int CONDITION = -2;
static final int PROPAGATE = -3;
// 状态字段,取上述 4 个状态值。值为 0,表示非以上状态
volatile int waitStatus;
// 当前节点的前驱节点
volatile Node prev;
// 当前节点的后继节点
volatile Node next;
// 节点关联的线程
volatile Thread thread;
// 下一个处于等待条件的节点
Node nextWaiter;
// 判断节点是否以共享模式等待
final boolean isShared(){
return nextWaiter == SHARED;
}
// 如果有前驱节点,则返回该节点
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
Node() {
}
// addWaiter 使用。给线程添加等待模型
Node(Thread thread, Node mode) {
this.nextWaiter = mode;
this.thread = thread;
}
// Condition 使用,给线程添加等待条件
Node(Thread thread, int waitStatus) {
this.waitStatus = waitStatus;
this.thread = thread;
}
}
4.2 对 Node 的 CAS 操作
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long stateOffset;
private static final long headOffset;
private static final long tailOffset;
private static final long waitStatusOffset;
private static final long nextOffset;
static {
try {
stateOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("state"));
headOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("head"));
tailOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
waitStatusOffset = unsafe.objectFieldOffset
(Node.class.getDeclaredField("waitStatus"));
nextOffset = unsafe.objectFieldOffset
(Node.class.getDeclaredField("next"));
} catch (Exception ex) { throw new Error(ex); }
}
/**
* 使用 unsafe 类对 Node 进行原子更新。如果当前状态值等于预期值,则以原子方式将同步状态设置为给定的更新值。
*/
private final boolean compareAndSetHead(Node update) {
return unsafe.compareAndSwapObject(this, headOffset, null, update);
}
private final boolean compareAndSetTail(Node expect, Node update) {
return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
}
private static final boolean compareAndSetWaitStatus(Node node,
int expect,
int update) {
return unsafe.compareAndSwapInt(node, waitStatusOffset,
expect, update);
}
private static final boolean compareAndSetNext(Node node,
Node expect,
Node update) {
return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
}
4.3 队列中的 Node 操作
/**
* 将节点加入队列,必要时进行初始化
*/
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) {
// 尾结点为空,需要初始化
if (compareAndSetHead(new Node()))
tail = head;
} else {
// 尾结点不为空,unsafe进行插入节点
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
/**
* 为当前线程设置指定模式。并加入队列
*/
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
/**
* 设置头结点
*/
private void setHead(Node node) {
head = node;
node.thread = null;
node.prev = null;
}
/**
* 如果存在后继节点则进行唤醒操作
*/
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
Node s = node.next;
if (s == null || s.waitStatus > 0) {
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);
}
5. 内部类 ConditionObject
ConditionObject 实现了 Condition 接口。Condition 对象是由 Lock 对象创建的。
/**
* 等待队列中的头结点
*/
private transient Node firstWaiter;
/**
* 等待队列中的尾结点
*/
private transient Node lastWaiter;
ConditionObject 核心的两个方法:await() 、signal()
5.1 await() 方法
- 当前线程进入等待状态,直到被通知(signal)或中断
- 当前线程将进入运行状态且从 await() 方法返回的情况:
- 其他线程调用该 Condition 的 signal() 或 signalAll() 方法
- 其他线程调用 interrupt() 方法中断当前线程
- 如果等待线程从 await() 方法返回,则该线程已经获取了 Condition 对象所对应的锁
5.2 signal() 方法
唤醒一个等待在 Condition 上的线程,该线程从等待方法返回前必须获得与 Condition 相关联的锁
signal() 为唤醒一个线程,signalAll() 为唤醒所有等待的线程
6. 获取和释放资源的方法
独享方式:acquire(int arg)、acquireInterruptibly(int arg)、release(int arg)
共享方式:acquireShared(int arg) 、acquireSharedInterruptibly(int arg)、releaseShared(int arg)
6.1 独享方式
/**
* 获取独享锁
* tryAcquire 需要子类重写方法
*/
public final void acquire(int arg) {
// 尝试获取锁,获取成功返回 true,否则返回 false
if (!tryAcquire(arg) &&
// 没有获取则加入队列尾部,并通过 LockSupport.park(this)挂起自己
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
// 进行自我中断
selfInterrupt();
}
// 线程自我中断
static void selfInterrupt() {
Thread.currentThread().interrupt();
}
/**
* 试着释放当前线程持有的独占锁并唤醒后继节点
*/
public final boolean release(int arg) {
// tryRelease 独享式释放同步状态,需要子类重写
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
/**
* 获取独占锁的可中断模式
*/
public final void acquireInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
// 当前线程如果中断,则抛出中断异常
throw new InterruptedException();
if (!tryAcquire(arg)) // 尝试获取锁
// 获取锁失败,则调用 doAcquireInterruptibly 获取独享锁的可中断模式
doAcquireInterruptibly(arg);
}
6.2 共享方式
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0)
// 获取共享锁的不中断模式
doAcquireShared(arg);
}
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}