AQS的理解

本文详细解析了AQS(AbstractQueuedSynchronizer)作为Java同步框架的基础,探讨了其维护的共享资源状态、volatile变量、FIFO等待队列,以及ReentrantLock和Semaphore的实现原理。还比较了公平锁与非公平锁的区别,以及LockSupport在唤醒线程方面的优势。
摘要由CSDN通过智能技术生成
  • 概念

    • AQS(AbstractQueuedSynchronizer)是一个抽象的队列同步器,通过维护一个共享资源状态State和一个FIFO的线程等待队列来实现一个多线程访问共享资源的同步框架

    • AQS提供了一个模板,可以通过AQS实现不同的同步器,ReentrantLock、Semaphore都是基于AQS

    • 多个线程竞争共享资源变量(state)被阻塞时就会进入等待队列中

  • state(共享资源变量)

    • Abstract Queued Synchronizer 维护了 volatile int 类型的变量,用于表示当前的同步状态

      • volatile虽然不能保证操作的原子性,但是能保证当前变量state的可见性

  • FIFO等待队列

    • 多个线程竞争共享资源变量(state)被阻塞时就会进入等待队列中

  • ReentrantLock加锁解锁

    • 加锁

      • 线程 A、B、C 同时抢占锁,此时线程 B 抢占成功,线程 A、C 则失败

      • 线程 B 抢占锁的过程中把 state 通过 cas 更新为 1,并且设置当前线程同步器的持有者是线程B

        • 设置当前线程同步器的持有者是线程B是为了防止抢占

        • 实现可重入,也就是我当前线程B可以在我没有释放锁的前提下再一次获得锁

      • 线程 A、C 因为更新失败,所以也就抢占失败

      • 抢占锁失败的线程,都会被放入到一个 FIFO 的线程等待队列中(双向链表)

      • head、tail 分别指向队列的头和尾

    • 解锁

      • 线程 B 通过 cas 把 state 更新为 0

      • 唤醒等待队列中head节点线程 A

    • 公平锁、非公平锁

      • 公平锁

        • 按照队列中的等待顺序,依次取队头的线程(比如上面的例子中,下一个获取锁的线程一定是线程 A)

      • 非公平锁

        • 在释放锁后,如果有新的线程尝试获取锁,有可能会抢占成功(比如在线程B释放锁的瞬间,有个 新的线程 D,尝试获取锁,有很大几率会抢占成功)

  • Locksupport

    • 在 AQS 中,队列中线程阻塞唤醒都是通过 LockSupport 实现的

    • LockSupport类的核心方法

      • park():阻塞当前调用线程

      • unpark():唤醒指定线程

    • 相比Object 类中的 wait()、notify()、notifyAll()区别

      • wait/notify/notifyAll 必须在 synchronized中使用

      • LockSupport 操作更精准,可以准确地唤醒某一个线程

  • 10
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值