备注:博文仅仅是学习过程中的零散记录,后期整理。
AbstractQueuedSynchronizer的简单介绍可以网上搜索,简单了解字段作用。
示例代码,分析获取锁的过程:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class AQS {
public static void main(String[] args) { Lock lock = new ReentrantLock(); lock.lock(); // do something lock.unlock(); } }
调用lock方法,然后间接调用:
/**
* Sync object for non-fair locks
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L; /**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
if (compareAndSetState(0, 1))//更新state的状态值,state是用来记录获取锁的情况。state=0的话则锁没有人获取,当大于0时候表示锁被获取。重入次数。
setExclusiveOwnerThread(Thread.currentThread()); //AQS的exclusiveOwnerThread成员,记录当前获取锁的线程
else
acquire(1);
} protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
调用如上代码的lock方法,其中的compareAndSetState调用底层操作系统的CAS方法,是一个原子操作。到此就完成了获取锁。
接下来看看重入锁申请过程,java.util.concurrent.locks.ReentrantLock.Sync.nonfairTryAcquire(int):
/**
* Performs non-fair tryLock. tryAcquire is
* implemented in subclasses, but both need nonfair
* try for trylock method.
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread(); //当获取重入锁时候,判断当前线程和之前申请锁的线程是否是一个?如果不是一个的话则直接返回false
int c = getState();
if (c == 0) { //第一次获取锁时,state为0
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//如果不是第一次的话,则重入锁
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires; //acquires参数每一次获取锁时候,参数acquires都为1,代表依次获取锁。nextc是当前一共获取锁的次数
if (nextc < 0) // overflow ,重入次数过多,导致大于Int最大值溢出,抛异常
throw new Error("Maximum lock count exceeded");
setState(nextc);//更新state状态值
return true; //获取锁成功
}
return false;
}
接下来看看释放锁的过程,java.util.concurrent.locks.ReentrantLock.Sync.tryRelease(int):
//unlock最终调用这个方法释放锁
protected final boolean tryRelease(int releases) {
int c = getState() - releases; //判断state的值,释放锁进行一次减1操作
if (Thread.currentThread() != getExclusiveOwnerThread())//判断释放锁的线程和当初获取锁的线程是否是一个线程,不是的话则抛异常
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {//如果锁已经彻底释放,则将获取锁的线程设置为null
free = true;
setExclusiveOwnerThread(null);
}
setState(c);//更新state的状态
return free;
}
重入锁的释放同上。