首页 > 其他分享 >JUC:AQS

JUC:AQS

时间:2023-05-28 19:00:12浏览次数:42  
标签:Node JUC AQS 队列 共享资源 volatile 线程 节点

AQS 是 JUC 的基石,提供了数据结构和底层实现方法,比如获取锁的方式由子类实现完成出入队、唤醒线程由功能。这里只分析 AQS 已经实现了的功能逻辑,如果要分析完成的功能需要配合具体的子类比如 ReentrantLock

核心思想

如果共享资源空闲,当前线程就工作,并锁住资源。如果共享资源被占用当前线程就进入队列,并等到条件合适及时唤醒

资源占用方式

独占:又分为公平(严格排队,先进先出)和非公平(插队,插不成功就排队,就是公平锁了),比如 ReentrantLock
共享:实现的有 Semaphore/CountDownLatch。Semaphore、CountDownLatCh、 CyclicBarrier、ReadWriteLock

内部重要属性

private transient volatile Node head; // 队头
private transient volatile Node tail; // 队尾
private volatile int state; // 共享资源状态
static final class Node; // 内部类 Node
public class ConditionObject; // 内部类 ConditionObject
  1. head 和 tail:对头与队尾,队头不是同步队列中的第一个节点(第一个线程是正在工作的线程,没理由放入等待队列)

  2. state:共享资源状态,同步状态,资源被占用次数

    1. 0 共享资源未被使用,1 表示共享资源已被使用,大于1表示重入锁(同一个线程多次访问共享资源)
    2. 为什么需要这个值?不然直接读内存吗?每个线程都会缓存这个值,一个线程更新,别的线程可见(volatile保证)
    3. 比如 reentrantlock.tryLock() 初次获取锁成功 cas 更新的时候,如果是 0 才更新为1,不然就失败
  3. 内部类 Node:同步队列中的节点,是由线程封装出来的,每个节点有两个指针分别指向前一个和后一个

    static final Node SHARED = new Node();// 占用资源方式:共享
    static final Node EXCLUSIVE = null;// 占用资源方式:独占
    volatile int waitStatus;// 当前节点状态
    volatile Node prev;// 前驱指针,指向前一个节点
    volatile Node next;// 后驱指针
    volatile Thread thread;// 结点所对应的线程    
    Node nextWaiter;// 也是一个指针,指向下一个处于 CONDITION 状态的节点
    

    waitStatus 当前节点的状态,不要和 aqs 中的 state 混淆了,aqs 的 state 是共享资源的状态,waitStatus 是每个节点的状态,取值范围如下:

    状态 含义
    CALCELLED 1 获取锁的线程被取消了
    CONDITION -2 表示节点在等待队列中,线程需要等待唤醒
    PROPAGATE -3 共享锁模式下才会使用,独占锁不会用
    SIGNAL -1 线程已经准备好了,就等资源释放

入队过程

  • lock() 方法作为入口,tryAcquire 方法获取锁,如果获取成功,就没后续步骤了,也不会维护队列,节点状态等

    • tryAcquire cas 算法更改 aqs 的 state
    • 由子类实现,比如 ReentrantLock 的公平和非公平
  • 如果 tryAcquire 获取锁失败,就要维护队列了,aqs 的 addWaiter 方法已经实现好了的,逻辑如下

    • 如果此时队列为空,执行 enq 方法创建一个节点,不初始化任何属性(虚拟节点),作为队头(aqs 的 head)
    • 如果队列不为空,不会执行 enq,只是维护链表,当前节点作为队尾,并维护指向关系
  • 入队成功后执行 acquireQueued,两个作用:更改前一个节点状态和挂起当前节点的线程

出队过程

  • 都是由 unLock() 方法作为入口
  • 更改 aqs 的 head 和 tail 指向
    • 涉及链表操作,顺便把下一个节点唤醒

标签:Node,JUC,AQS,队列,共享资源,volatile,线程,节点
From: https://www.cnblogs.com/hangychn/p/17438657.html

相关文章

  • 八、JUC-原子类
    一、基本类型原子类首先,我们来用原子类实现i++的效果,可以看出,结果并不是50000packagecom.lori.juc2023.juc8;importjava.util.concurrent.atomic.AtomicInteger;publicclassAtomicDemo1{publicstaticfinalintSIZE=50;publicstaticvoidmain(Strin......
  • 七、JUC-CAS
    一、原子类java.util.concurrent.atomic下所有的类二、没有用CAS之前多线程下不使用原子类保证线程安全i++(基本数据类型)packagecom.lori.juc2023.juc7;publicclasscasDemo1{volatileintnumber=0;//读取publicintgetNumber(){returnnumber......
  • 五、JUC-Java内存模型JMM
    一、一些疑问什么是Java内存模型JMMJMM与volatile他们两个之间的关系JMM有哪些特性为什么要有JMM,他们为什么出现,功能和作用是什么happens-before先行发生原则是什么二、计算机硬件存储体系计算机存储结构,从本地磁盘到主存到CPU缓存,也就是从硬盘到内存到CPU一般对应的程序......
  • 四、JUC-LockSupport与线程中断
    一、线程中断机制1、概述一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止,所以,Thread.stop、Thread.suspend、Thread.resume都已经被废弃了在Java中没有办法立即停止一条线程,然而停止线程却显得尤为重要,如取消一个耗时操作。因此,Java提供了一种用于......
  • AQS源码解读----AbstractQueuedSynchronizer
    36packagecn.com.pep;37importjava.util.concurrent.TimeUnit;38importjava.util.concurrent.locks.AbstractOwnableSynchronizer;39importjava.util.concurrent.locks.Condition;40importjava.util.concurrent.locks.LockSupport;41importjava.......
  • 【面试系列5】JUC
    并行与并发并行:多个机器同时执行并发:一个机器分时执行Future接口定义了操作异步任务执行的一些方法,获取异步任务执行的结果,取消任务的执行,判断任务是否被取消,判断任务执行完毕。多线程/有返回/异步任务classMyThread2implementsCallable<String>{@Overridepu......
  • 3.JUC【Java面试第三季】
    3.JUC【Java面试第三季】前言推荐3.JUC06_闲聊AQS面试1.题目+说明07_可重入锁理论2.可重入锁说明“可重入锁”这四个字分开来解释可重入锁的种类08_可重入锁的代码验证-上09_可重入锁的代码验证-下3.LockSupport10_LockSupport是什么LockSupport是什么11_waitNotify限制==线程等待......
  • JUC中的Semaphore,最简单的限流工具类
    Semaphore(信号量)为多线程协作提供了更为强大的控制方法,前面的文章中我们学了synchronized和重入锁ReentrantLock,这2种锁一次都只能允许一个线程访问一个资源,而信号量可以控制有多少个线程可以同时访问特定的资源。Semaphore常用场景:限流举个例子:比如有个停车场,有5个空位,门口有......
  • 【JUC】原子操作
     juc包下的原子类针对基础类型地原子性读写而设计的原子类:AtomicBooleanAtomicIntegerAtomicIntegerArrayAtomicIntegerFieldUpdater<T>AtomicLongAtomicLongArrayAtomicLongFieldUpdater<T>针对引用类型地原子性读写而设计的原子类:......
  • 什么是AQS
    AQS(AbstractQueuedSynchronizer),即队列同步器,它是构建锁或者其他同步组件的基础框架,如ReentrantLock、ReentrantReadWriteLock、Semaphore,CountDownLatch等。AQS是一个抽象类,主要是通过继承方式使用,本身没有实现任何接口,仅仅是定义了同步状态的获取和释放的方法。AQS解决了了之类......