public class ReentrantLock implements Lock {// 加锁入口方法public void lock() {// 调用Sync中加锁方法sync.lock();}}
在子类NonfairSync的加锁方法:
// 非公平锁static final class NonfairSync extends Sync {// 加锁final void lock() {// 1. 先尝试加锁(使用CAS设置state=1)if (compareAndSetState(0, 1))// 2. 加锁成功,就把当前线程设置为持有锁线程setExclusiveOwnerThread(Thread.currentThread());else// 3. 没加锁成功,再调用父类AQS中实际的加锁逻辑acquire(1);}}
加锁逻辑也很简单,先尝试使用CAS加锁(也就是把state从0设置成1),加锁成功,就把当前线程设置为持有锁线程 。
设计者很聪明,在锁竞争不激烈的情况下,很大概率可以加锁成功,也就不用走else中复杂的加锁逻辑了 。
如果没有加锁成功,还是需要走else中调用父类AQS的acquire方法,而acquire又需要调用子类的tryAcquire方法 。
调用链路就是下面这样:
文章插图
根据调用链路,实际的加锁逻辑在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方法:文章插图
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 公平锁源码先看一下公平锁的加锁流程:
文章插图
最终的加锁方法是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());}}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 【深入浅出 Yarn 架构与实现】2-4 Yarn 基础库 - 状态机库
- 硬核剖析Java锁底层AQS源码,深入理解底层架构设计
- 一 OpenMP 教程 深入人剖析 OpenMP reduction 子句
- 【深入浅出 Yarn 架构与实现】2-2 Yarn 基础库 - 底层通信库 RPC
- Helm干货!速度围观!
- 【深入浅出 Yarn 架构与实现】2-1 Yarn 基础库概述
- 【深入浅出 Yarn 架构与实现】1-2 搭建 Hadoop 源码阅读环境
- 海味干货批发进货渠道
- 干货批发市场进货渠道有哪些
- 【深入浅出 Yarn 架构与实现】1-1 设计理念与基本架构