ReentrantLock的实现原理

本文介绍了ReentrantLock作为可重入独占锁的特性,与synchronized的区别,以及其公平锁机制。ReentrantLock通过AbstractQueuedSynchronizer(AQS)实现,利用state同步标志位和CLH队列管理线程竞争。AQS有两种资源共享模式:独占模式用于ReentrantLock的加锁和释放,共享模式则具有资源传播特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ReentrantLock 简介

ReentrantLock 实现了 Lock 接口,是一种可重入的独占锁。

相比于 synchronized 同步锁,ReentrantLock 更加灵活,拥有更加强大的功能,比如可以实现公平锁机制。

首先,先来了解一下什么是公平锁机制。

ReentrantLock 的公平锁机制

我们知道,ReentrantLock 分为公平锁非公平锁,可以通过构造方法来指定具体类型:

//默认非公平锁
public ReentrantLock() {
    sync = new NonfairSync();
}
 
//公平锁
public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

公平锁

在多个线程竞争获取锁时,公平锁倾向于将访问权授予等待时间最长的线程。

也就是说,公平锁相当于有一个线程等待队列,先进入队列的线程会先获得锁,按照 "FIFO(先进先出)" 的原则,对于每一个等待线程都是公平的。

非公平锁

非公平锁是抢占模式,线程不会关注队列中是否存在其他线程,也不会遵守先来后到的原则,直接尝试获取锁。

接下来进入正题,一起分析下 ReentrantLock 的底层是如何实现的。

ReentrantLock 的底层实现

ReentrantLock 实现的前提是 AbstractQueuedSynchronizer(抽象队列同步器),简称 AQS,是 java.util.concurrent 的核心,常用的线程并发类 CountDownLatch、CyclicBarrier、Semaphore、ReentrantLock 等都包括了一个继承自 AQS 抽象类的内部类。

同步标志位 state

AQS 内部维护了一个同步标志位 state,用来实现同步加锁控制:

private volatile int state;

同步标志位 state 的初始值为 0,线程每加一次锁,state 就会加 1,也就是说,已经获得锁的线程再次加锁,state 值会再次加 1。可以看出,state 实际上表示的是已获得锁的线程进行加锁操作的次数。

CLH 队列

除了 state 同步标志位外,AQS 内部还使用一个 FIFO 的队列(也叫 CLH 队列)来表示排队等待锁的线程,当线程争抢锁失败后会封装成 Node 节点加入 CLH 队列中去。

Node 的代码实现:

static final class Node {
      // 标识当前节点在共享模式
      static final Node SHARED = new Node();
      // 标识当前节点在独占模式
      static final Node EX
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

春日安然

可以赏个鸡腿吃嘛~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值