自学AQS
相关属性
exclusiveOwnerThread => 当前获取锁的线程
state => 状态
傻瓜式学习AQS
- AbstractQueuedSynchronizer继承了AbstractOwnableSynchronizer
- ReentrantLock reentrantLock = new ReentrantLock(true);
- 进入方法reentrantLock.lock();
- IDEA快捷键alt+7查看ReentrantLock内部类
- abstract void lock();IDEA快捷键ctrl+alt+b查看实现有2个
FairSync 公平同步
//RL->FS->
final void lock() {
acquire(1);
}
//AQS->
public final void acquire(int arg) {
//获取锁失败了 -> 入队!
if (!tryAcquire(arg) &&
//去阻塞
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
//RL->FS->
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//0表示无锁状态。同步器允许被持有
//因为是公平锁所以得看看有没有排队的
if (c == 0) {
//如果 队列里面没有排队的
if (!hasQueuedPredecessors() &&
//并且cas把同步器0->1
compareAndSetState(0, acquires)) {
//我占有了!
setExclusiveOwnerThread(current);
return true;
}
}
//有人持有了锁 是不是自己呢?是就把同步器加1不是返回false
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
//AQS->
//线程入队
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;
}
//AQS
private Node enq(final Node node) {
//自旋
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;
}
}
}
}
//AQS->
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
//获取当前节点的前一个节点
final Node p = node.predecessor();
//阻塞涉及内核态和用户态切换所以如果你是队列第一个就会再抢一次
//成功的话 节点出队,并且把head往后挪一个节点,新的头结点就是当前节点,旧的head变成垃圾被GC
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
//针对于shouldParkAfterFailedAcquire
//第一轮循环 把head状态改成-1(为了解锁时候用) 返回false
//第二轮循环 返回true 执行parkAndCheckInterrupt 线程停在这 唤醒值会从这运行
//阻塞线程,并且需要判断线程是否是有中断信号唤醒的
//咋唤醒啊 等unlock() 见下面
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
//AQS->
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
//node进来初始化都是0
//p是前一个节点(为了后面节点服务) node是当前节点
//正常head节点初始值为0 进最下面的判断会把waitStatus改为-1 是为了表示下一个节点可以被唤醒
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)return true;
if (ws > 0) {
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
//将当前节点状态改为-1
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
//对应上面
public void unlock() {
sync.release(1);
}
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
//头不为空 并且waitStatus不为0(对应之前的改为-1)
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
//改变state为0 唤醒
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
//解锁 node是head 又把head的状态改成0了
private void unparkSuccessor(Node node) { 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);
}
未完待续。。。