AQS之独占模式

本文详细介绍了AQS(AbstractQueueSynchronizer)的独占模式,包括AQS的介绍、双端链表Node的结构以及独占模式的获取和释放操作。AQS是Java并发库的核心,用于构建锁和同步器。独占模式的获取分为tryAcquire、addWaiter和acquireQueued三个步骤,释放操作则涉及Node状态的改变和线程的唤醒。
摘要由CSDN通过智能技术生成

目录

 

​前序

AQS介绍

双端链表Node

独占方式.获取操作

独占方式.释放操作


​前序

 

在学习AQS源码的时候,勾勾先介绍两个在AQS中比较重要的知识:线程interrupt方法和CAS乐观锁。

与线程中断相关的API有如下几个:

 //中断方法,其他线程调用阻塞线程的intrrrupt方法,可以打断阻塞状态
public void interrupt() {... }
//判断当前线程是否中断,仅仅是对interrupt标识的判断,没有做其他事情
 public boolean isInterrupted() {
        return isInterrupted(false);
  }
//判断当前线程是否中断,但是改方法会擦除线程的interrupt标识,
//如果当前线程被中断了,那么第一次调用返回true,且立即擦除标识,以后再调用就是false
 public static boolean interrupted() {
     return currentThread().isInterrupted(true);
 }

CAS是乐观锁的主要实现:在更新的时候先比较当前值是否与期望的值相等,相等则更新,不相等则不更新,从而保证并发编程下共享变量的安全性。

CAS是比较简单的乐观锁,在这里只做简单介绍,勾勾在后面的文章《锁的分类》会重点讲解。

了解这两个知识点后,我们就开始AQS源码的学习吧。

AQS是JUC包的核心,勾勾的学习分为源码和实现类,源码的学习分3篇文章:独占模式(EXCLUSEIVE)、共享模式(SHARED)、条件等待(CONDITION)。

接下来就开始学习独占模式的获取操作和释放操作的源码,篇幅比较长,很多信息会写在源码的注释上,注意查收喔。

 

AQS介绍

 

AQS(AbstractQueueSynchronizer)是一个用于构建锁和同步器的框架,许多同步容器都可以通过AQS很容易并且高效的构建出来。java.util.concurrent中的许多可阻塞类,例如ReentrantLock、Semaphore、ReentrantReadWriteLock、CountDownLatch、SynchronousQueue和FutureTask等,都是基于AQS的。

在基于AQS构建的同步器中,最基本的操作包括各种形式的获取和释放操作。AQS负责管理同步容器类中的状态,它管理了一个整型的状态信息,可以通过getState,setState以及compareAndSetState等protected类型的方法来操作。这个整型状态可以代表任意状态,在不同的实现类中有不同的含义。例如ReentrantLock用它来表示所有者线程重复获取改锁的次数,Semphore用它来表示剩余的许可数量,FutureTask用它来表示任务的状态。

所以整个AQS的源码既是围绕state的获取和修改。

我们先来了解AQS的成员变量:

  /**
     * 等待队列的头节点,惰性初始化。  只有在执行setHead方法的时候才会被修改。
     * 如果头节点存在,则需保证它的状态不是CANCELLED
     */
    private transient volatile Node head;

    /**
     * 等待队列的尾节点, 惰性初始化.  只有向队列中添加元素的时候才会修改
     */
    private transient volatile Node tail;

    /**
     * 同步器的状态
     */
    private volatile int state;

 //获取同步器的状态
 protected final int getState() {
        return state;
    }
   //设置同步器的状态
    protected final void setState(int newState) {
        state = newState;
    }
   //cas方式设置同步器的状态
    protected final boolean compareAndSetState(int expect, int update) {       
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

通过对AQS的成员变量分析,除了关键的同步器状态之外,另一个关键的信息就是Node对象,那么我们就先看看Node是一个什么样的类。

 

双端链表Node

 

Node是AQS中的一个静态不可变的内部类,其结构是一个FIFO的双端链表,主要用来维护线程以及节点的等待状态。它的源码如下:

static final class Node {
        /** 节点在共享状态下等待的标记 */
        static final Node SHARED = new Node();
        /** 节点在独占状态下等待的标记 */
        static final Node EXCLUSIVE = null;
        /** 因超时或者中断节点处于取消状态,取消状态的节点线程不再参与锁的竞争 */
        static final int CANCELLED =  1;
        /** 该节点的后继节点处于等待状态,当该节点的线程释放了锁后ÿ
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值