备注:博文仅仅是学习过程中的零散记录,后期整理。
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; }
重入锁的释放同上。