J.U.C包核心AQS(一):快速了解AQS

AQS 是个啥?

AQS,全称 AbstractQueuedSynchronizer,中文直译过来就是 “抽象的队列式的同步器”,它定义了多线程访问共享资源的同步器框架,J.U.C 包中很多同步类实现都依赖于它,比如我们常用的锁:ReentrantLock,又比如一些常用的并发工具类:CountDownLatch、Semaphore 等等。所以,很多人称 AQS 为 J.U.C 包的核心。那么要想吃透 J.U.C 的源码思想,第一步要做的当然就是彻底弄懂 AQS 啊!
 

AQS 的组成

AQS 整体上来看有两个核心组成部分:

  • 一个 int 型的成员变量,它用来表示同步状态。
  • 一个 FIFO 双向队列,它用来完成竞争资源的线程的排队工作。

我们接下来具体的来看一下这两个重要的组成部分。

一、同步状态

private volatile int state;

我们可以看到,成员变量 state 是被关键字 volatile 修饰了的,这里主要是为了保证 state 这个变量在多个线程之间的可见性。

那么所谓的加锁/解锁,其实就是对 state 这个同步状态的获取,类似于操作系统中实现进程同步的信号量,多个进程通过检查信号量的值来判断是否可以进入临界区。

同步器的主要使用方式是继承,子类通过继承 AQS 并实现它的抽象方法来管理同步状态,在抽象方法的实现过程中免不了要对同步状态进行更改,这时就需要使用同步器提供的三个方法来操作同步状态:

  • getState():获取当前同步状态
  • setState(int newState):设置当前同步状态
  • compareAndSetState(int expect,int update):使用 CAS 设置当前状态,该方法能够保证状态设置的原子性

源码如下:

    protected final int getState() {
   
        return state;
    }

    protected final void setState(int newState) {
   
        state = newState;
    }
    
    protected final boolean compareAndSetState(int expect, int update) {
   
        // See below for intrinsics setup to support this
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

我们主要来看一下 compareAndSetState(int expect, int update) 这个方法,看名字你就能知道,只要以 ”CompareAndxxxxx “ 开头的,基本上就是使用 unsafe 类的 CAS 操作没跑了,主要是为了保证设置同步状态的操作原子性。

二、同步队列

AQS 通过内置的 FIFO 同步队列来完成资源获取线程的排队工作,如果当前线程获取同步状态失败(锁)时,AQS 则会将当前线程以及等待状态等信息构造成一个节点(Node)并将其加入同步队列,同时会阻塞当前线程,当同步状态释放时,则会把节点中的线程唤醒,使其再次尝试获取同步状态。

本文旨在先对 AQS 做一个简单的介绍,同步队列的具体内容在该系列的下一篇文章中。

 

AQS 的使用详解与示例

同步器的设计是基于模板方法模式的,也就是说,使用者需要继承同步器并重写指定的方法,随后将同步器组合在自定义同步组件的实现中,并调用同步器提供的模板方法,而这些模板方法将会调用使用者重写的方法。

那么,接下来我们就来看看,哪些方法是可以重写的,哪些方法是模板方法。

一、可重写方法:

在介绍可重写方法之前,要先让大家明确一点,那就是以下这些方法,不是需要你全部重写(所以这里说的是重写),这需要根据你想要实现锁的类型(独占锁还是共享锁)来决定你需要重写的方法。

  • tryAcquire(int arg):独占式获取同步状态
  • tryRelease(int arg):独占式释放同步状态
  • tryAcquireShared(int arg):共享式获取同步状态
  • tryReleaseShared(int arg):共享式释放同步状态
  • isHeldExclusively():当前同步器是否在独占式模式下被线程占用,一般该方法表示是否被当前线程所独占

我们可以看出来,这些开发人员可以重写的方法,几乎都是围绕着同步状态的获取与释放来提供的,我们来看一下 AQS 中的源码。

    protected boolean tryAcquire(int arg) {
   
        throw new UnsupportedOperationException();
    }

    protected boolean tryRelease(int arg) {
   
        throw new UnsupportedOperationException();
    }

    protected int tryAcquireShared(int arg) {
   
        thr
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值