AbstractQueuedSynchronizer
首先了解AQS内最核心的变量
- private volatile int state; 控制锁状态变量
- private transient Thread exclusiveOwnerThread; 是父类AbstractOwnableSynchronizer中的属性,表示当前占锁的线程
- 内部对象node 是用于保存线程的节点,多个节点组成队列
从ReentrantLock加锁和释放锁的过程来理解
1.调用ReentrantLock的lock()方法尝试进行加锁
以非公平锁为例
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
首先调用AQS的compareAndSetState方法,upsafe类的CAS方法,作用是将stateOffset与expect做比作比较。
相等就把update值赋值给stateOffset位置的值。方法返回true。
不相等,就取消赋值,方法返回false
protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
如果CAS操作成功,则加锁完成,并同时设置占锁线程是当前线程,如果失败则调用 acquire(1);
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
先执行tryAcquire(1)会再次尝试加锁,先判断当前锁状态,如果无锁占用,则直接加锁,如果有在看看占锁线程是不是就是自己,如果是则重入,就是将状态status在加1,如果不是则确认加锁失败
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
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;
}
加锁如果失败了,会调用acquireQueued(addWaiter(Node.EXCLUSIVE), arg),将当前的线程放入队列,并中断当前线程
2.调用unlock()方法解锁
调用AQS的release方法尝试释放锁,如果锁完全释放了,并且存在等待节点的话,则通过unparkSuccessor(h)来唤醒一个等待节点来获取锁
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
tryRelease方法就是对当前线程的线程状态 -1,直到现在状态status=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;
}