AbstractQueuedSynchronizer的介绍和原理分析

本文深入剖析了AbstractQueuedSynchronizer (AQS)的工作原理,包括其如何利用FIFO队列构建锁和同步机制,以及如何通过状态管理实现独占锁和共享锁的功能。

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

  • 介绍:
    • 提供了一个基于FIFO队列,可以用于构建锁或者其他同步装置的基础框架,
    • 利用了一个int类型表示状态
    • 使用方法是继承
    • 子类通过继承并通过实现它的方法管理其状态{acquire 和release}的方法操纵状态
    • 可以同时实现排它锁和共享锁模式
  • 源码内使用:
      • 使用类型:
        • 独占类型
        • 共享类型
  • 内部属性:
    • 队列保存线程引用和线程状态的容器, 将线程对同步器的一次访问,看作一个Node
      • Node(节点):
      • 属性名称
        说明
        waitStatus 1.SINGAL=-1 : 当前节点的后继节点需要运行,也就是unpark
        2.CANCELLED=1:当前节点被取消
        3.CONDIITION=-2 : 表示当前节点在等待Condition ,也就是Condition队列
        4.propagate=-3:便是当前场景下后序的acquireshare能够得以执行
        5.  0 :当前节点在sync队列中,等待获得锁 
        nextWaiter  存储在Condition队列中的后继节点

  • 同步队列,依托node构建 : 
    • 同步器拥有syn队列的3个成员变量:
      •  头节点:head         尾节点:tail    状态 :state
  • 构造函数:
    •  protected AbstractQueuedSynchronizer() { }
  • 主要接口
    • acquire(intr arg)
      • 该方法以排他的方式获取锁,对中断不敏感,完成synchronized语义。
      • 源码:
        • tryacquire需要子类自己去实现,交给子类去实现{以ReentrantLock--fairLock为例子

        • 未获取到,就生成waitor加入队列中
      • 原理
    • release()
      • 而release则表示将状态设置回去,也就是将资源释放,或者说将锁释放。
      • 源码解析:

        • 原理:
        •  该方法取出了当前节点的next引用,然后对其线程(Node)进行了唤醒,这时就只有一个或合理个数的线程被唤醒,被唤醒的线程继续进行对资源的获取与争夺。
    • private boolean doAcquireNanos(int arg, long nanosTimeout) throws InterruptedException
      • 原理
    • public final void acquireShared(int arg)
      • 调用该方法能够以共享获取状态,
      • 逻辑:
        • 尝试获取共享状态;
          • 调用tryAcquireShared(arg)方法获得
        • 获取失败加入syn队列
          • 以共享锁模式加入队列
        • 循环退出条件
          • 当前节点的前驱节点是否为头节点且能够获取共享状态
          • 与独占锁的退出机制一致
        • 判断共享状态成功
          • 将当前节点设为头节点,判断后继节点是否为共享模式
          • 如果是,则唤醒该线程,对其进行唤醒操作,也就是同时激发多个线程并发的运行
        • 获取状态失败 
          • 使用LockSupport.park(this);将线程从调度器上摘下,进入休休眠状态
    • public final boolean releaseShared(int arg)
      • 每次获取共享状态acquireShared都会操作状态,同样在共享锁释放的时候,也需要将状态释放。
  • 总结:
    • 这篇文章,我们从ReentrantLock出发,完整的分析了AQS独占功能的API及内部实现。
    • 总的来说,思路其实并不复杂,还是使用的标志位+队列的方式,记录获取锁、竞争锁、释放锁等 一系列锁的状态,或许用更准确一点的描述的话,应该是使用的标志位+队列的方式,记录锁,竞争,释放等一系列独占的状态,因为站在AQS的层面state可以表示锁,也可以表示其他状态,它并不关心它的子类把它变成一个什么工具类,而只是提供了一套维护一个独占状态。
    • 甚至,最准确的是AQS只是维护了一个状态,因为,别忘了,它还有一套共享状态的API,所以,AQS只是维护一个状态,一个控制各个线程何时可以访问的状态,它只对状态负责,而这个状态表示什么含义,由子类自己去定义。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值