锁专题(五)ReentrantLock 深入源码详解

点赞再看 , 已成习惯 。
锁专题(五)ReentrantLock 深入源码详解文章插图
可重入锁源码
ReentrantLock 源码介绍 ReentrantLock 的文章很多 , 今天我们来一起看一下 ReentrantLock 的源码 , 理解一下实现原理 。
类定义ReentrantLock 实现了 Lock 接口 , 和序列化接口 。
/** * @author 老马啸西风 */public class ReentrantLock implements Lock, java.io.Serializable {private static final long serialVersionUID = 7373984872572414699L;/** Synchronizer providing all implementation mechanics */private final Sync sync;}Sync 介绍Sync 作为可重入锁的私有变量 , 实际上是继承自 AQS 的一个锁实现 。
关于部分方法的解释我写在了注释中 , 便于大家理解 。
ps:AQS 我们本节不做展开 , 后续会专门有一节进行讲解 。
/** * Base of synchronization control for this lock. Subclassed * into fair and nonfair versions below. Uses AQS state to * represent the number of holds on the lock. * @author 老马啸西风 */abstract static class Sync extends AbstractQueuedSynchronizer {private static final long serialVersionUID = -5179523762034025860L;/*** Performs {@link Lock#lock}. The main reason for subclassing* is to allow fast path for nonfair version.*/abstract void lock();/*** Performs non-fair tryLock.tryAcquire is implemented in* subclasses, but both need nonfair try for trylock method.** 非公平获取锁 。* (1)如果当前没有线程持有锁 , 则通过 CAS 比较 , 如果 state=0 , 且设置为 acquires 成功 , 则设置持有锁的线程为当前线程 。* (2)如果持有锁的线程已经是当前线程 , 则设置 state += acquires;* 这里还很细心 , 做了一个防止 overflow 的处理 。*/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) // overflowthrow new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}/*** 尝试释放锁* (1)如果当前进程不是最后一个设置锁的进程(锁的持有者) , 则报错* (2)c = 当前状态-释放的个数 。* 如果 c = 0 , 说明锁已经被完全释放 , 设置所的持有者为 null , 更新 state=c , 返回 free 的结果 。*/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;}/*** 判断当前线程是否为持有者*/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 ownerreturn getExclusiveOwnerThread() == Thread.currentThread();}/*** 创建一个 ConditionObject*/final ConditionObject newCondition() {return new ConditionObject();}// Methods relayed from outer class/*** 获取锁持有者*/final Thread getOwner() {return getState() == 0 ? null : getExclusiveOwnerThread();}/*** 获取锁持有者的数量*/final int getHoldCount() {return isHeldExclusively() ? getState() : 0;}/*** 判断是否处于加锁状态*/final boolean isLocked() {return getState() != 0;}/*** Reconstitutes the instance from a stream (that is, deserializes it).*/private void readObject(java.io.ObjectInputStream s)throws java.io.IOException, ClassNotFoundException {s.defaultReadObject();setState(0); // reset to unlocked state}}非公平锁实现源码这里的非公平锁实现直接继承自 Sync 。
/** * Sync object for non-fair locks * @author 老马啸西风 */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))setExclusiveOwnerThread(Thread.currentThread());elseacquire(1);}/*** 尝试获取锁的实现很简单 , 直接调用 Sync 中的方法 。*/protected final boolean tryAcquire(int acquires) {return nonfairTryAcquire(acquires);}}lock 方法这里我们讲解下 lock() 方法 , 这个是一个加锁的方法 。
if (compareAndSetState(0, 1)) 意思就是当 state=0 且设置为1成功时 , 设置锁的持有者为当前线程 。
否则就调用 acquire(1); , 这个方法是 AQS 中的一个方法:
/** * Acquires in exclusive mode, ignoring interrupts.Implemented * by invoking at least once {@link #tryAcquire}, * returning on success.Otherwise the thread is queued, possibly * repeatedly blocking and unblocking, invoking {@link * #tryAcquire} until success.This method can be used * to implement method {@link Lock#lock}. * * @param arg the acquire argument.This value is conveyed to *{@link #tryAcquire} but is otherwise uninterpreted and *can represent anything you like. * @author 老马啸西风 */public final void acquire(int arg) {if (!tryAcquire(arg) }