ReentrantLock是基于AQS实现的,它提供了公平锁与非公平锁两种策略,当然这两种策略都是抢占式的。其核心代码是对AQS的公平、非公平的实现,下面我们来看其核心代码:
内部类Sync,该类定义为抽象类,并继承自AbstractQueuedSynchronizer,它还会被NonfairSync(非公平策略)与FairSync(公平策略)两个类继承。主要关注nonfairTryAcquire方法与tryRelease方法
// Sync类继承自AbstractQueuedSynchronizer, abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = -5179523762034025860L; // ReentrantLock的lock方法就是调用这个方法,由子类实现。 abstract void lock(); // 这个方法提供了对非公平锁策略的实现 final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); // 只有当state为0时,才可以竞争锁 if (c == 0) { // 与公平锁的主要区别在这里,下面会提供公平锁的实现。 // 非公平锁直接用CAS尝试修改AQS的state,而没考虑排队情况,因此是不公平的 // 公平锁只会让处于head的线程去修改state,相当于排队了,因此是公平的 // 如果state修改成功,会通过setExclusiveOwnerThread方法将当前线程设置为exclusiveOwnerThread,表示竞争成功 if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } // 注意,这里实现了可重入性!这种情况是state!=0,即当前锁是被线程占有的,但是如果占有该锁的线程就是当前线程,那么还是能够修改state // 获取到1次,state=acquires // 获取到2次,state=2*acquires // 依次类推 // 在release的时候也会一层一层的减回去,因此要保证lock与unlock次数一样 else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires;//这里会state累加 if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } // 该方法提供了锁的释放,不论是公平还是不公平锁,都用这个实现 // 这里release的值与tryAcquire中acquires的值应该相等,不然会出现锁完全释放后,state!=0的情况,那就凉了。。。 protected final boolean tryRelease(int releases) { int c = getState() - releases; // 保证释放锁的线程,必须拥有锁,不然抛出异常 if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); // 如果释放完之后,state的值确实为0,那么将获得锁的线程设置为null // 注意,这里也支持重入性,如果释放完之后,c不为0,那么当前线程还可以继续释放。 boolean free = false; if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; } // 这是对isHeldExclusively实现,即判断当前线程是否exclusiveOwnerThread protected final boolean isHeldExclusively() { // While we must in general read state before owner, // we don't need to do so to check if current thread is owner return getExclusiveOwnerThread() == Thread.currentThread(); } // 对Condition的支持 final ConditionObject newCondition() { return new ConditionObject(); } // 其它方法很简单省略... }
NonfairSync,继承自Sync,非公平锁策略,实现很简单,因为Sync已经都实现了非公平的策略
static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; /** * 实现lock方法。先通过compareAndSetState尝试获取一次,如果成功则获取锁。 * 否则走acquire,详见AbstractQueuedSynchronizer源码解析。 */ final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } // 重写tryAcquire,直接调用Sync的nonfairTryAcquire方法。 protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } }
FairSync,继承自Sync,公平策略。需要实现公平策略的tryAcquire
static final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L; // 区别1:这里没有先尝试获取一次,因为公平模式必须要排队。而非公平模式不用考虑队列,所以可以先使用compareAndSetState获取一次 final void lock() { acquire(1); } /** * 公平锁策略 */ protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { // 主要区别在这里,在竞争之前,先判断!hasQueuedPredecessors() // 如果当前线程在队首,则hasQueuedPredecessors返回false if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } }