AQS源码
前言
未完待续
一、
Lock {
自旋
park - unpark
cas
}
AQS 队列里面的对头 里面的Thread 永远为null;
一、AQS成员变量?
//state 共享资源是否被占用,的标记位
//int 类型是因为 存在共享模式, 如果都是共享模式则都可以访问, 所以不是boolean
private volatile int state;
//未获取到资源则进入等待队列 FIFO 先进先出的双向链表
//队列头
private transient volatile Node head;
//队列尾
private transient volatile Node tail;
//得到state
protected final int getState() {
return state;
}
//设置state
protected final void setState(int newState) {
state = newState;
}
//比较请交换,源语操作
protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
// 没有获取到锁则进入等待队列, Node 节点信息
static final class Node {
static final Node SHARED = new Node();
static final Node EXCLUSIVE = null;
volatile Node prev;
volatile Node next;
volatile Thread thread;
Node nextWaiter;
}
二、ReentrantLock 获取锁解析
三、关键源码
1、获取锁
获取到锁一次,不管是否获取都返回boolean 。tryAcquire
一定要获取锁,未获取到锁则进入等待列队。acquire
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
2、未获取到 则创建节点 进入等待队列
public final void acquire(int arg) {
//获取锁,
if (!tryAcquire(arg) &&
//未获取到 则创建节点 进入等待队列
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
3、addWaiter 入队构造 Node节点
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// 尝试enq的快速路径;故障时备份到完整enq
Node pred = tail;
if (pred != null) {
//将新节点的上一个节点设置成tail
node.prev = pred;
if (compareAndSetTail(pred, node)) {
//将以前的尾节点设置成当前节点
pred.next = node;
return node;
}
}
//第一次入队
enq(node);
return node;
}
第一次入队构造节点 重点。
private Node enq(final Node node) {
//死循环,第一次tail = null,然后进去 new Node 了一个节点,然后tail = head = null
//第二次则不等于 null 将当前节点的pre 置为 上一次那个new 出来的 tail = head = null 节点
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
入队
//入队
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);
}
}
自旋
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);
}
}