干货,深入剖析ReentrantLock源码,推荐收藏( 二 )


干货,深入剖析ReentrantLock源码,推荐收藏

文章插图
根据调用链路,实际的加锁逻辑在Sync.nonfairTryAcquire方法里面 。
abstract static class Sync extends AbstractQueuedSynchronizer {// 非公平锁的最终加锁方法final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();// 1. 获取同步状态int c = getState();// 2. state=0表示无锁,先尝试加锁(使用CAS设置state=1)if (c == 0) {if (compareAndSetState(0, acquires)) {// 3. 加锁成功,就把当前线程设置为持有锁线程setExclusiveOwnerThread(current);return true;}// 4. 如果当前线程已经持有锁,执行可重入的逻辑} else if (current == getExclusiveOwnerThread()) {// 5. 加锁次数+acquiresint nextc = c + acquires;// 6. 超过tnt类型最大值,溢出了if (nextc < 0)throw new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}}再看一下释放锁的调用流程 , 公平锁和非公平锁流程是一样的,最终都是执行Sync.tryRelease方法:
干货,深入剖析ReentrantLock源码,推荐收藏

文章插图
abstract static class Sync extends AbstractQueuedSynchronizer {// 释放锁protected final boolean tryRelease(int releases) {// 1. 同步状态减去释放锁次数int c = getState() - releases;// 2. 校验当前线程不持有锁,就报错if (Thread.currentThread() != getExclusiveOwnerThread())throw new IllegalMonitorStateException();boolean free = false;// 3. 判断同步状态是否等于0 , 无锁后,就删除持有锁的线程if (c == 0) {free = true;setExclusiveOwnerThread(null);}setState(c);return free;}}再看一下公平锁的源码
3.3 公平锁源码先看一下公平锁的加锁流程:
干货,深入剖析ReentrantLock源码,推荐收藏

文章插图
最终的加锁方法是FairSync.tryAcquire,看一下具体逻辑:
static final class FairSync extends Sync {// 实现父类的加锁逻辑protected final boolean tryAcquire(int acquires) {final Thread current = Thread.currentThread();// 1. 获取同步状态int c = getState();// 2. state=0表示无锁,先尝试加锁(使用CAS设置state=1)if (c == 0) {// 3. 判断当前线程是不是头节点的下一个节点(讲究先来后到)if (!hasQueuedPredecessors() &&compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}// 4. 如果当前线程已经持有锁,执行可重入的逻辑} else if (current == getExclusiveOwnerThread()) {// 5. 加锁次数+acquiresint nextc = c + acquires;// 6. 超过tnt类型最大值,溢出了if (nextc < 0)throw new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}// 判断当前线程是不是头节点的下一个节点(讲究先来后到)public final boolean hasQueuedPredecessors() {Node t = tail;Node h = head;Node s;return h != t &&((s = h.next) == null || s.thread != Thread.currentThread());}}公平锁的释放锁逻辑跟非公平锁一样,上面已经讲过 。
4. 总结看完了ReentrantLock的所有源码,是不是觉得ReentrantLock很简单 。
由于加锁流程的编排工作已经在父类AQS中实现,子类只需要实现具体的加锁逻辑即可 。
加锁逻辑也很简单,也就是修改同步状态state的值和持有锁的线程exclusiveOwnerThread 。
我是「一灯架构」,如果本文对你有帮助,欢迎各位小伙伴点赞、评论和关注,感谢各位老铁,我们下期见

干货,深入剖析ReentrantLock源码,推荐收藏

文章插图
【干货,深入剖析ReentrantLock源码,推荐收藏】

推荐阅读