aqs独享锁模式源码
package java.util.concurrent.locks;
public abstract class AbstractQueuedSynchronizer
// AbstractOwnableSynchronizer 独享锁专用, 维护当前持锁线程, 兼容可重入锁
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
// aqs继承序列化类有什么用? 带锁网络传输
private static final long serialVersionUID = 7373984972572414691L;
// 抽象队列同步器 (自旋+阻塞 CLH自选锁变体 隐式链表队列锁)
protected AbstractQueuedSynchronizer() { }
/*
* +------+ prev +-----+ +-----+
* head | | <---- | | <---- | | tail
* +------+ +-----+ +-----+
*/
static final class Node {
/** 独享模式 */
static final Node EXCLUSIVE = null;
/** 取消 */
static final int CANCELLED = 1;
/** 当前节点为SIGNAL, 释放锁时会unpark 后续节点.*/
static final int SIGNAL = -1;
// 独占锁, 只用到以上两种状态
/**
* 普通同步节点 初始化为0
* 使用CAS修改状态 或者 volatile set(尽量使用无条件volatile写入 性能会好一些).
*/
volatile int waitStatus;
volatile Node prev;
volatile Node next;
// 节点线程. 构造时初始化 使用后置null.
volatile Thread thread;
/**
* 返回前驱节点.
* 可以忽略null, NullPointerException help VM.
*/
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
Node() { // 用于创建head
}
Node(Thread thread, Node mode) { // 创建独享锁节点
this.nextWaiter = mode;
this.thread = thread;
}
}
/**
* 等待队列头 懒加载. 除了初始化之外,它只通过setHead方法进行修改。
* Note: 如果head存在, 它的等待状态 != CANCEL
*/
private transient volatile Node head;
// 等待队列尾 懒加载. 通过方法enq, 添加新的等待节点.
private transient volatile Node tail;
/**
* 独享模式下保证线程互斥, 只有一个线程进入临界区, 其他等待。
* 同步状态 不同数值代表:获得锁,释放锁
* 数值可以自定义 比如1: 获得锁 0:释放锁
* 在tryAcquire tryRelease 中使用
* tryAcquire tryRelease 需要用户实现且互斥
* 虽然 JSR-166 对64-bit long支持原子性操作, 需要不同平台的内部锁的支持,造成同步器性能不行.
*/
private volatile int state;
// memory semantics 读内存语义
protected final int getState() {
return state;
}
// memory semantics 写内存语义
protected final void setState(int newState) {
state = newState;
}
// 具有读写的内存语义
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
// Main exported methods 主要对外开放接口
/**
* 尝试获取独享锁. 这个方法查询对象是否允许以独占模式获得它.
*
* 线程执行此方法尝试获取锁,获取失败如果未排队,acquire method会调用入队方法
*/
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
/**
* 尝试set state(int类型 不同数值代表 获得锁 释放锁)
* <p>总是在 thread 执行 release 时被调用.
*
* @param arg the release argument. 这个值会经过release传进来,
* @throws IllegalMonitorStateException 如果释放使同步器处于非法状态
* @throws UnsupportedOperationException 如果不支持独享模式
*/
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
/**
* 独占锁模式获取, ignoring interrupts.
* 如果{@link
* 线程可能反复的阻塞唤醒, 知道 {@link
*/
public final void acquire(int arg) {
// 如果tryAcquire成功, 不加入等待队列, 提高效率.
if (!tryAcquire(arg) &&
// addWaiter: 创建节点加入等待队列
// acquireQueued 将队列的前一个节点状态设置为signal
// signal状态的节点释放锁时能唤醒下一个节点
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
// 释放独享锁. 唤醒队列中的下一个节点去争抢锁
public final boolean release(int arg) {
if (tryRelease(arg)) {
// --------------- tryRelease ---------------
// 当tryRelease return true 才能进入下面的方法, 安全区
Node h = head;
// h.waitStatus 不能为cancel 不能为0 只剩下signal
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
// --------------- tryRelease ---------------
}
return false;
}
/*----------------- 队列方法 -----------------*/
// 插入队尾, 必要时初始化
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // 懒加载
// 此处和 setHead 有访问冲突, 使用cas防止数据争用
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
// cas 可分解为读写两步 性能消耗也相当于volatile 读写:
// 1. 比较 pred 和 当前的 tail
// 2. 如果 pred == tail 将 tail 替换成 node
// 3. 如果 pred != tail 调用 enq(node)
// cas是原子性操作, 确保 (pred)oldTail 和 node(new tail) 的前后关系
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
/**
* 节点的 创建/插入队尾
* @param mode Node.EXCLUSIVE 独享锁, Node.SHARED 共享锁
*/
private Node addWaiter(Node mode) {
// new Node() 无需考虑ABA问题
Node node = new Node(Thread.currentThread(), mode);
// 尝试最短路径入队; 失败使用 完整的 enq;
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
/**
* 插入表头, 退出等待队列. 仅仅通过acquire调用.
* 防止不必要的 唤醒信号和遍历
*/
private void setHead(Node node) {
head = node;
// 置空, 为了方便GC, 防止不必要的 唤醒信号和遍历
node.thread = null;
node.prev = null;
}
// 唤醒后继结点
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
// 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);
}
// acquire 工具类
// 修改pred节点状态为Signal
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
// 前一个Node状态为SIGNAL, 当前节点可以被唤醒, 可以安全的park当前节点
if (ws == Node.SIGNAL)
return true;
// 其他情况 返回false
if (ws > 0) { //取消状态
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
// waitStatus must be 0(独享锁模式) or PROPAGATE(共享锁模式). 修改为 SIGNAL
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
static void selfInterrupt() {
// 中断当前线程
Thread.currentThread().interrupt();
}
private final boolean parkAndCheckInterrupt() {
// 挂起线程
LockSupport.park(this);
// 返回中断状态
return Thread.interrupted();
}
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
// 自选锁
for (;;) {
final Node p = node.predecessor();
// 前节点是head && 尝试获取锁
if (p == head && tryAcquire(arg)) {
// 当前节点设置为头节点
// ------------ tryAcquire 安全区 ------------
// 只有获得锁的线程能够执行 执行以下代码保证了头节点的同步安全
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
// ------------ tryAcquire 安全区 ------------
}
// shouldParkAfterFailedAcquire 获取锁失败后,设置前一个节点为SINGAL
if (shouldParkAfterFailedAcquire(p, node) &&
// parkAndCheckInterrupt 挂起线程并检查是否中断
parkAndCheckInterrupt()){ // 被唤醒后重新走一遍当前流程
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
private void cancelAcquire(Node node) {
if (node == null)
return;
node.thread = null;
Node pred = node.prev;
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
Node predNext = pred.next;
node.waitStatus = Node.CANCELLED;
if (node == tail && compareAndSetTail(node, pred)) {
compareAndSetNext(pred, predNext, null);
} else {
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
}
}
// 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;
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"));
} catch (Exception ex) { throw new Error(ex); }
}
// CAS head field. Used only by enq.
private final boolean compareAndSetHead(Node update) {
return unsafe.compareAndSwapObject(this, headOffset, null, update);
}
// CAS tail field. Used only by enq.
private final boolean compareAndSetTail(Node expect, Node update) {
return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
}
// CAS waitStatus field of a node.
private static final boolean compareAndSetWaitStatus(Node node, int expect, int update) {
return unsafe.compareAndSwapInt(node, waitStatusOffset, expect, update);
}
}
列举 aqs 独享锁中 中的共享变量
1. volatile int state
2. Node() {
volatile int waitStatus
volatile Node prev;
3. volatile Node head
4. volatile Node tail
列举 aqs 独享锁中 涉及同步动作,同步顺序的代码
protected final int getState() {
return state;
}
protected final void setState(int newState) {
state = newState;
}
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
private static final boolean compareAndSetWaitStatus(Node node, int expect, int update) {
return unsafe.compareAndSwapInt(node, waitStatusOffset, expect, update);
}
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);
}
// 都是无锁cas的方法 或者 volatile的读/写
// cas保证原子性的同时 性能消耗约等于 volatile 读+写