AbstractQueueSynchronizer简称AQS的理解

我是一个使者,不为所斩,但求已知

AbstractQueueSynchronizer,抽象的队列式同步器, 简称 AQS,一般用于支持其他框架,在多线程中常用

工作原理:

   把所有请求线程构成一个CLH队列,当一个线程执行完毕lock.unlock时会激活自己后续节点,正在执行的线程不在队列中,等待执行的线程全部处于阻塞状态
比如ReentrantLock,先通过CAS尝试获取锁。如果此时已经有线程占据了锁,那就加入CLH队列 队尾并且被挂起 自旋。当锁被释放之后,排在CLH队列队首的线程会被唤醒,然后CAS再次尝试获取锁。

在这个时候,如果:

  非公平锁:如果同时还有另一个线程进来尝试获取,那么有可能会让这个线程抢先获取
  公平锁: 如果同时还有另一个线程进来尝试获取,当它发现自己不是在队首的话,就会排到队尾,由队首的线程获取到锁。

  AQS维护一个共享资源volatile的整型变量state,通过内置的FIFO来完成获取资源线程的排队工作。(这个内置的同步队列称为**"CLH"队列**:带头节点的双向非循环链表)。该队列由一个一个的Node结点组成,每个Node结点维护一个prev引用和next引用,分别指向自己的前驱和后继结点。AQS维护两个指针,分别指向队列头部head和尾部tail。
结构如下
在这里插入图片描述

参考大神画好的图😂😂😂😂😂

应用

  我们常用的CountDownLatch、ReentrantLock、Semaphore等类都是在内部定义了一个叫做Sync的内部类,而Sync类继承了AQS抽象类并重写了一些必要的方法,这是作为公平/非公平的设置

  对于Semaphore来说,state用来表示当前可用信号的个数;

  对于CountDownlatch来说,state用来表示计数器当前的值

  独占锁以ReentrantLock为例,state初始值为0,表示未锁状态,当一个线程执行了lock()方法之后,会调用tryAcquire方法独占该锁并将state+1,此后其他线程尝试获取锁时便会失败,进入队列,直到刚才的线程释放锁将state值更改为0时,其他线程才有机会获取这个独占锁。当然,这个锁时可重入的,获得锁的线程可以继续state+1,不过只有state为0的时候其他线程才会唤醒。

  共享锁以CountDownLatch为例,初始化线程数为n,及将state初始值设置为n,表示可以有n个线程同时获取这个共享锁,当有线程执行一countDown(),state就会CAS的方式减少1,知道所有线程执行完,state值为0的时候,会unpark主线程,然后主线程会从await状态被唤醒返回,继续执行其他指令。

  一般情况自定义同步器要么是独占方法,要么是共享方式,他们也只需实现tryAcquire-tryRelease、tryAcquireShared-tryReleaseShared中的一种即可。需要说明的是AQS也支持同时实现独占同步和共享同步,比如ReentrantReadWriteLock。

以上都是通过其内部compareAndSetState方法设置,这个方法被引用了多少大家可以自己看一下,我先截个图
在这里插入图片描述
好了,今天就到这里,祝你好运!🤞🤞🤞🤞🤞

借鉴:https://www.cnblogs.com/ZoHy/p/11300095.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

站长大人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值