通俗易懂的AQS核心源码解析

本文深入浅出地介绍了AQS(AbstractQueuedSynchronizer)的核心源码,通过生活中的银行取钱场景类比,阐述了AQS如何实现线程同步。文章详细解析了acquire和release方法,解释了state变量、CLH队列、volatile和CAS的重要性,并探讨了ReentrantLock和CountDownLatch的实现原理。此外,还解答了volatile、CAS自旋、park()和unpark()的相关问题。

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

最好懂的AQS核心源码

相必大家应该都在各个八股文里听过AQS吧。只要你简历里写上你会多线程,这个知识点几乎是必问的。

在阅读之前,读者希望你们对ReentrantLock和CountDownLounch()两个类有过使用经历。

什么是AQS?

AQS的全称就是 AbstractQueuedSynchronizer,翻译过来就是抽象队列同步器,这是JUC包中的一个类。

这个类很关键,很多并发工具类都是基于这个类实现的,他也是JUC同步框架的基石。

实现类需要去继承该类,并重写指定方法就可以实现一套线程同步机制。

我们经常用到的ReentrantLock和CountDownLatch等也都是基于AQS实现的。

从生活角度理解AQS

AQS的设计就和取钱的场景很类似,1号,2号,3号选手都在银行取钱,柜台只有一个,因此同一时间只有一个人可以取钱。1号在取钱的时候,2号,3号都会在等待区等待。1号取完后,会通知2号,2号再去取。

AQS框架

AQS核心

AQS的核心只有两个东西:

  1. 一个用volatile修饰的state变量(最后有讲解)
  2. 一个CLH(三个人名缩写)的双向队列。

每一个线程获取锁的时候,就会试图去修改state变量,如果修改成功就能获取锁,如果失败,就自动加入双向队列的末尾,等待持有锁的线程对其进行释放。

这里就可以理解成银行取钱,只有一张票,获得票的人可以取钱,取完后,把这个票给另一个在等待的人,另一个人就能取钱了

其中,AQS对state的访问设置了三种方法:

  • getState()
  • setState()
  • compareAndSetState()

其中compareAndSetState 就是 CAS 法的思想体现。它结合了CAS自旋 volatile 变量(最后有讲解)。

两种资源共享方式

AQS定义了两种资源共享方式:Exclusive(独占的,仅一个线程可以执行,如ReentrantLock)和Share(共享的,如CountDownLatch)

不同自定义同步器争用共享资源的方式不同。在实现自定义同步器的时候,只需要实现state的释放和获取的方式即可。

像ReentrantLock,CountDownLatch都是jdk里实现了以下方法的自定义同步器

自定义同步器需要实现以下几种方法:

独占式(比如ReentrantLock)

  1. tryAcquire(int) : 独占的资源共享方式。尝试获取资源,成功返回true,失败返回false
  2. tryRelease(int) : 独占的资源共享方式。尝试释放资源,成功返回true,失败返回false

共享式(比如CountDownLatch)

  1. tryAcquireShared(int):共享的资源共享方式。尝试获取资源,负数表示失败,0表示成功,但没有剩余资源,正数表示成功,有剩余资源。
  2. tryReleaseShared(int):共享的资源共享方式。尝试释放资源。

ReentrantLock为例(独占)

以ReentrantLock为例,state初始化是0,表示未锁定状态。A线程调用ReentrantLock的lock()方法时,同时会调用tryAcquire()方法,抢占锁,并且将state+1。此后所有的线程去执行tryRelease方法都会失败,直到A线程调用ReentrantLock的unLock()方法,也就是调用ryRelease(int)方法,state会变成0,之后其他线程才能获得到锁。当然A线程在锁的时候,也是可以重复获取锁的,每重复获取一次,state+1,在释放的时候,获得多少次就要减多少次。

CountDownLatch为例(共享)

以CountDownLatch为例,当你在构造器里面传入一个参数n的时候,state也会被初始化成n。每个

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值