AQS原理

 AQS的全称是AbstractQueuedSynchrizeder(抽象队列同步器)。它是为实现依赖于先进先出等待队列的阻塞锁和各种同步器(Semaphore,CountdownLatch,CyclicBarrier,Exchanger等等)而提供的一种基础框架。

  它内部有一个int类型的state变量,被volatile关键字修饰,保证线程之间的可见。还会维护一个Node内部类(用于生成同步对列和等待队列),并继承过来一个加锁线程。state变量的访问方式有三种:getState(),setState(int),compareAndSetState(int,int)三个方法。AQS定义了两种资源共享的方式,独占模式和共享方式。

  使用此类:

   为了将此类用作同步器的基础,需要适当的重新定义以下方法,这是通过使用getState(),setState(int),compareAndSetState(int,int)三个方法来检查或修改同步状态来实现的。

        tryAcquire(int)       试图在独占模式下获取对象状态,由acquire自动调用,至少调用一次

        tryRelease(int)      试图设置状态来反映独占模式下的一个释放,由release自动调用,至少调用一次

        tryAcquireShared(int)         试图在共享模式下获取对象状态,由acquireShared自动调用,至少调用一次

         tryReleaseShared(int)      试图设置状态来反映共享模式下的一个释放,由releaseShared自动调用,至少调用一次

  默认情况下,每个方法都抛出UnsupportedOperationException。这些方法的实现在内部必须是线程安全的,通常应该很短并且不被阻塞。

AQS的源码中涉及到的锁有独占锁与共享锁,独占锁就是只有一个线程可以获取锁,共享锁就是同时可以有多个线程获取锁。
代码层体现下AQS的state属性,为0,则锁没有被线程所持有,独占锁时为1,共享锁时大于0,代表获取此锁的现成的数量。
AQS的内部类Node定义了两个常量SHARED和EXCLUSIVE,他们分别标识AQS队列中等待线程的锁的获取模式。

        /**
         * The synchronization state.
         */
        private volatile int state;

JUC中ReentrantLock与CyclicBarrier为独占锁,CountDownLatch与Semaphore为共享锁,
ReentrantReadWriteLock中writeLock为独占锁,ReadLock为共享锁。

独占锁与共享锁的区别:

  • 独占功能
    当锁被头节点获取后,只有头节点获取锁,其余节点的线程继续沉睡,等待锁被释放后,才会唤醒下一个节点的线程。
  • 共享功能
    只要头节点获取锁成功,就在唤醒自身节点对应的线程的同时,继续唤醒AQS队列中的下一个节点的线程,每个节点在唤醒自身的同时还会唤醒下一个节点对应的线程,以实现共享状态的“向后传播”,从而实现共享功能。

  ReentrantLock就是使用AQS而实现的一把锁,它实现了可重入锁,公平锁和非公平锁。它有一个内部类用作同步器是Sync,Sync是继承了AQS的一个子类,并且公平锁和非公平锁是继承了Sync的两个子类。ReentrantLock的原理是:假设有一个线程A来尝试获取锁,它会先CAS修改state的值,从0修改到1,如果修改成功,那就说明获取锁成功,设置加锁线程为当前线程。如果此时又有一个线程B来尝试获取锁,那么它也会CAS修改state的值,从0修改到1,因为线程A已经修改了state的值,那么线程B就会修改失败,然后他会判断一下加锁线程是否为自己本身线程,如果是自己本身线程的话它就会将state的值直接加1,这是为了实现锁的可重入。如果加锁线程不是当前线程的话,那么就会将它生成一个Node节点,加入到等待队列的队尾,直到什么时候线程A释放了锁它会唤醒等待队列队头的线程。这里还要分为公平锁和非公平锁,默认为非公平锁,公平锁和非公平锁无非就差了一步。如果是公平锁,此时又有外来线程尝试获取锁,它会首先判断一下等待队列是否有第一个节点,如果有第一个节点,就说明等待队列不为空,有等待获取锁的线程,那么它就不会去同步队列中抢占cpu资源。如果是非公平锁的话,它就不会判断等待队列是否有第一个节点,它会直接前往同步对列中去抢占cpu资源。

  以下是ReentrantLock的原理图解,简单明了:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AQS(AbstractQueuedSynchronizer)是 Java 并发包中一个重要的同步组件,它通过内部维护一个 FIFO 队列来实现同步协作,是很多同步组件的基础,例如 ReentrantLock、CountDownLatch、Semaphore 等。 AQS 内部基于一个 int 类型的变量 state 来表示同步状态,当 state 为 0 时表示未锁定状态,当 state 大于 0 时表示已锁定状态,小于 0 时表示 state 的绝对值是等待获取同步状态的线程个数。AQS 的操作主要包括独占和共享两种模式,独占模式下只有一个线程能够获取同步状态,共享模式下可以有多个线程同时获取同步状态。 AQS 的核心是一个双向链表,其中每个节点表示一个等待线程,通过 CAS 操作来实现节点的加入和移除。在独占模式下,等待线程会被加入到队列的尾部,当前获取同步状态的线程是队列头部的节点,当当前线程释放同步状态后,会唤醒队列中的下一个节点。在共享模式下,等待线程也会被加入到队列的尾部,但是当前获取同步状态的线程可能是队列中的任意一个节点,当当前线程释放同步状态后,会唤醒队列中的所有节点。 AQS 组件包括以下几种: 1. ReentrantLock:可重入锁,支持公平和非公平两种模式。 2. ReentrantReadWriteLock:读写锁,支持读写分离。 3. Semaphore:信号量,用于控制资源的并发访问量。 4. CountDownLatch:倒计时门闩,用于等待其他线程完成一定的操作后再执行。 5. CyclicBarrier:循环屏障,用于等待一组线程达到某个状态后再执行。 6. Condition:条件变量,用于在某个条件下等待或唤醒线程。 以上就是 AQS 的基本原理和组件介绍。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值