AQS 队列同步器详解

本文详细介绍了AQS(AbstractQueuedSynchronizer)队列同步器,包括其提供的接口、实现原理及独占式与共享式同步状态的获取与释放。AQS基于CLH同步队列,利用模板方法模式简化了锁和其他同步组件的实现。
摘要由CSDN通过智能技术生成

参考:Java并发编程的艺术

JDK版本:AdoptOpenJDK 11.0.2+9

1 AQS 队列同步器

队列同步器(AbstractQueuedSynchronizerAQS)是用来构架锁或者其他同步组件的基础框架。它是面向锁的实现者的,它简化了锁的实现方式,屏蔽了同步状态管理、线程的排队、等待和唤醒等底层操作,大大降低了实现一个可靠的锁或者同步组件的门槛。

2 AQS 提供的接口

AQS是基于 模板方法模式 设计的。使用者需要继承同步器并重写指定的方法来操作同步状态,使用的时候要调用同步器提供的模板方法。

下面对同步器提供的方法一一说明。

2.1 访问或修改同步状态的方法

AQS提供了3个方法来访问或修改同步状态:

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

2.2 可重写的方法

AQS提供了一些可以被重写的方法,这些方法主要是来获取、释放同步状态的。

这些方法都是protected类型的,可以被子类重写。

方法 说明
protected boolean tryAcquire(int arg) 独占式获取同步状态。实现该方法需要查询当前同步状态并判断同步状态是否符合预期,然后再进行CAS设置同步状态。
protected boolean tryRelease(int arg) 独占式释放同步状态。释放后,等待获取同步状态的线程将有机会获取同步状态。
protected int tryAcquireShared(int arg) 共享式获取同步状态。返回大于等于0的值,表示获取成功;反之,获取失败。
protected boolean tryReleaseShared(int arg) 共享式释放同步状态。
protected boolean isHeldExclusively() 当前同步器是否在独占模式下被线程占用。一般该方法表示是否被当前线程所独占。

2.3 模板方法

AQS提供了一些模板方法,当实现自定义的同步组件的时候,将会调用这些模板方法,而这些模板方法将会去调用被重写的那些方法。

模板方法基本分为3类:独占式获取与释放同步状态共享式获取与释放同步状态查询同步队列中的等待线程

这些模板方法都是public final类型的,不可以被重写

方法 说明
public final void acquire(int arg) 独占式获取同步状态。如果当前线程获取同步状态成功,则该方法返回;否则,将会进入同步队列等待。该方法将会调用重写的tryAcquire(int age)方法。
public final void acquireInterruptibly(int arg) 独占式获取同步状态。该方法能够响应中断,当前线程如果没有获取到同步状态,则进入同步队列中等待,如果当前线程被中断,则会抛出InterruptedException异常。
public final boolean tryAcquireNanos(int arg, long nanosTimeout) acquireInterruptibly(int arg)基础上增加了超时限制,如果当前线程在超时时间内没有获取到同步状态,那么将会返回false,如果获取到返回true,如果被中断,抛出InterruptedException异常。
public final void acquireShared(int arg) 共享式获取同步状态。如果当前线程没有获取到同步状态,将会进入同步队列等待。与独占式的区别是在同一时刻可以有多个线程获取到同步状态。
public final void acquireSharedInterruptibly(int arg) acquireShared(int arg)相同,但是该方法能够响应中断。
public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout) acquireSharedInterruptibly(int arg)的基础上增加了超时限制。
public final boolean release(int arg) 独占式的释放同步状态。该方法将会在释放同步状态之后,将同步队列中第一个节点包含的线程唤醒。
public final boolean releaseShared(int arg) 共享式的释放同步状态。
public final Collection<Thread> getQueuedThreads() 获取等待在同步队列上的线程集合。

3 AQS 实现原理

3.1 Node节点

Node节点是对每一个等待获取同步资源的线程的封装,其中包含线程本身的引用及其等待状态,例如是否被阻塞、是否等待唤醒、是否已经被取消等。

源码如下:

    static final class Node {
   

        static final Node SHARED = new Node();

        static final Node EXCLUSIVE = null;

        static final int CANCELLED =  1;

        static final int SIGNAL    = -1;

        static final int CONDITION = -2;
        
        static final int PROPAGATE = -3;

        volatile int waitStatus;

        volatile Node prev;

        volatile Node next;

        volatile Thread thread;

        Node nextWaiter;

        ......
        
        final boolean compareAndSetWaitStatus(int expect, int update) {
   
            return WAITSTATUS.compareAndSet(this, expect
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值