当前位置: 首页 > article >正文

java源码阅读---ReentrantLock源码解析

ReentrantLock源码解读

在讲ReentrantLock之前我们先看一下Lock接口里的方法

Lock接口中的方法

lock()方法
void lock(); //直接加锁,如果加锁失败什么也不返回
lockInterruptibly()方法
void lockInterruptibly() throws InterruptedException;

lockInterruptibly()方法能够中断等待获取锁的线程。当两个线程同时通过lock.lockInterruptibly()获取某个锁时,假若此时线程A获取到了锁,而线程B只有等待,那么对线程B调用threadB.interrupt()方法能够中断线程B的等待过程。

tryLock()
boolean tryLock(); //直接加锁,如果加锁失败返回false
tryLock(long time, TimeUnit unit)
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;  // 尝试获取锁,如果没获取到锁,就等待一段时间,这段时间内还没获取到锁就返回false
unlock()方法
void unlock();//释放锁
newCondition()
Condition newCondition();// 条件锁

以上就是Lock接口中的方法,接下来我们看一下ReentrantLock的实现代码。

ReentrantLock的内部类

首先是ReentrantLock的三个内部类:Sync、NonfairSync、FairSync,其中NonfairSync类和FairSync类是继承Sync类

Sync类

首先Sync是一个静态的抽象类,下面我们看一下它的内部方法。

lock()
abstract void lock(); //抽象方法由子类实现
nonfairTryAcquire()
final boolean nonfairTryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {//判断当前是否有线程持有锁
        if (compareAndSetState(0, acquires)) {//使用CAS尝试加锁
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    else if (current == getExclusiveOwnerThread()) {//判断当前持有锁的线程是否是自己
        int nextc = c + acquires;
        if (nextc < 0) // overflow
            throw new Error("Maximum lock count exceeded");
        setState(nextc); //锁重入了,修改state的值
        return true;
    }
    return false;
}
tryRelease()

释放锁的方法

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;
}
isHeldExclusively()

判断锁是否是当前线程持有

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();
}
newCondition()

// 条件锁

final ConditionObject newCondition() {
    return new ConditionObject();
}
getOwner()

返回当前持有锁的线程,如果没有则返回null

final Thread getOwner() {
    return getState() == 0 ? null : getExclusiveOwnerThread();
}
getHoldCount()

当前线程持有此锁的次数,如果当前线程不持有此锁,则为零

final int getHoldCount() {
    return isHeldExclusively() ? getState() : 0;
}
NonfairSync类

NonfairSync是非公平锁的实现类,继承了Sync类。

lock()

加锁方法,因为是非公平锁所以在加锁的时候会先去尝试加锁,如果加锁失败则调用acquire()方法放入队列排队

final void lock() {
    if (compareAndSetState(0, 1))
        setExclusiveOwnerThread(Thread.currentThread());
    else
        acquire(1);
}
tryAcquire()

这里是调用父类的方法nonfairTryAcquire

protected final boolean tryAcquire(int acquires) {
    return nonfairTryAcquire(acquires);
}
FairSync类

FairSync公平锁的实现类

lock()

加锁方法

final void lock() {
    acquire(1);//调用父类的方法加锁
}
tryAcquire()
protected final boolean tryAcquire(int acquires) {
        final Thread current = Thread.currentThread();//获取当前线程
        int c = getState(); //获取锁标志位的值
        if (c == 0) {//判断锁是否被其他线程占用
            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;
    }
}

以上就是ReentrantLock的内部类了,接下来看一下构造方法

ReentrantLock的构造方法
无参构造方法

无参构造方法默认使用非公平锁

public ReentrantLock() {
    sync = new NonfairSync();
}
有参构造

传入参数为true时,是公平锁,false是非公平锁

public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}
ReentrantLock的其他方法

其他方法的调用主要主要看ReentrantLock使用的是公平锁还是非公平锁,这里就不一一介绍了;关于ReentrantLock的锁的实现还涉及到了AbstractQueuedSynchronizer、AbstractOwnableSynchronizer这两个类,这些我们后面再继续分析。


http://www.kler.cn/a/1739.html

相关文章:

  • 最优化学习笔记(一)
  • CPU、DPU、GPU
  • 音视频入门基础:MPEG2-TS专题(24)——FFmpeg源码中,显示TS流每个packet的pts、dts的实现
  • pthread_mutex_lock的概念和使用案例
  • WonderWorld 部署笔记
  • 路过石岩浪心古村
  • Monkey Test简单介绍
  • 树莓派(3B):启动流程,系统初始化配置,引脚图图示说明
  • 【云原生|Docker】04-docker的资源限制
  • 【小猫爪】AUTOSAR学习笔记06-Communication Stack之ComM模块
  • 2023年“网络安全”赛项江苏省淮安市赛题解析(超详细)
  • AI独立开发者:一周涨粉8万赚2W美元;推特#HustleGPT GPT-4创业挑战;即刻#AIHackathon创业者在行动 | ShowMeAI周刊
  • 使用Hexo+Github搭建部署个人博客
  • PyTorch 之 神经网络 Mnist 分类任务
  • 学习 Python 之 Pygame 开发魂斗罗(八)
  • 动态规划算法
  • 断言assert
  • 【多线程】多线程案例
  • GitHub 上有些什么好玩的项目?
  • 不是,到底有多少种图片懒加载方式?
  • 【正点原子FPGA连载】 第三十三章基于lwip的tftp server实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南
  • 修剪灌木[蓝桥杯2022初赛]
  • Java基础:笔试题
  • sharding-jdbc四种分片策略
  • 复制带随机指针的复杂链表
  • 【二】一起算法---队列:STL queue、手写循环队列、双端队列和单调队列、优先队列