锁专题(五)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) }
- 报名啦!宿迁开展第五届“十大科技之星”评选
- 苹果|iPhone13迎来变化!或回归指纹解锁,这几点备受用户喜爱
- 星期一|亚马逊:黑五与网络星期一期间 第三方卖家销售额达到48亿美元
- 绝不能|互联网也有“五连鞭”毒瘤,绝不能让这些“割韭菜者”一跑了之
- 早报:高通骁龙888正式发布 嫦娥五号传回首张图片
- 网购|黑色星期五及网购星期一大数据出炉 全球第三方卖家销售额超48亿美元
- 摄像头|华为Mate40或采用五摄加一传感器,摄像头越多真越好
- 手机|预算只有五千,买4G的iPhone11还是买国产5G安卓机?
- 至上|男人的工具箱:五金工具跟着我来买,实用至上,绝不吃灰
- 公园|长沙五一广场、烈士公园…湖南5G速度最快的地方是?