文章目录
- 什么是AQS?
- AQS与Synchronized的区别
- AQS-基本工作机制
- AQS是公平锁与非公平锁
什么是AQS?
全称是 AbstractQueuedSynchronizer,即抽象队列同步器
。它是构建锁或者其他同步组件的基础框架
所谓抽象,其实目的就是把具体的逻辑交给子类去实现,这样就可以实现不同的特性的锁:
例如:AQS常见的实现类
ReentrantLock阻塞式锁
Semaphore信号量
CountDownLatch倒计时锁
AQS是多线程中的队列同步器
。是一种锁机制
,它是做为一个基础框架
使用的,像ReentrantLock
、Semaphore
都是基于AQS实现的.
AQS其实是一个
抽象类
,它实现了线程挂起的逻辑
,实现了线程存储机制
,实现了锁的状态逻辑
,实现了线程唤醒的逻辑
,却只定义了线程抢锁
和释放锁
的抽象
,这样做的目的是将抢锁和释放锁的逻辑交给子类来实现
,这样有助于实现各种不同特性的锁,比如共享锁,独占锁,公平锁
,非公平锁
,可重入等。并且以模板方法模式将上述上锁流程和释放锁流程封装为固定模板方法。
所以AQS就是一个多线程访问共享资源的同步器框架。
AQS与Synchronized的区别
所以相比较Synchronized,基于AQS基础框架实现的各种特性不同的锁,对于解决多线程下锁的竞争可以提供不同的解决方案。
AQS-基本工作机制
AQS类自身有几个比较重要的属性:
```java
//正在持有锁的线程
private transient Thread exclusiveOwnerThread;
//等待队列的头节点
private transient volatile Node head;
//等待队列的尾节点
private transient volatile Node tail;
//锁标识字段
private volatile int state;
通过锁标识字段state
来标志线程是否拥有锁
AQS-多个线程共同去抢这个资源是如何保证原子性的呢:
通过CAS操作(比较再交换)
设置 state 状态,保证操作的原子性
当线程0和线程4同时去抢锁(修改state的值为1时)采用CAS的操作
,使得线程0将state设为1,这时线程4再去修改state时不满足CAS操作的规则
,这个时候不会自旋,而是直接加入(FIFO队列)等待队列。
AQS是公平锁与非公平锁
所谓公平不公平取决于:竞争的线程是队列的还是新的线程
新的线程
与队列中的线程
共同来抢资源,是非公平锁
新的线程到队列中等待,只让队列中的head线程获取锁
,是公平锁
公平锁:
当线程0释放锁的时候,让head指针指向的线程(线程1)去获取的锁执行自己的业务。
这就是公平锁
非公平锁:
当线程0释放锁的时候,正好又有一个新的线程(线程5)进来了,那么如果线程5拿到了锁,队列中的head指针指向的线程没有拿到锁,
这就是非公平锁
公平锁和非公平锁各有优缺点,适用于不同的场景。公平锁的优点
在于各个线程公平平等,每个线程等待一段时间后,都有执行的机会,而它的缺点
相较于于非公平锁整体执行速度更慢,吞吐量更低。同步队列中除第一个线程以外的所有线程都会阻塞
,CPU唤醒阻塞线程的开销比非公平锁大。
而非公平锁非公平锁的优点是可以减少唤起线程的开销,整体的吞吐效率高,因为线程有几率不阻塞直接获得锁,CPU不必唤醒所有线程
。它的缺点
呢也比较明显,即队列中等待的线程可能一直或者长时间获取不到锁。