AQS简介:
AQS全称为AbstractQueuedSynchronizer,翻译过来就是抽象队列同步器。使用AQS能够简单且高效地构造出应用广泛的大量的Synchronizer。不仅ReentrantLock 和 Semaphore是构建于AQS上的,其他的还有ReentrantReadwriteLock, countDownLatch和FutureTask等。
AQS解决了实现一个synchronizer的大量细节,比如等待线程的FIFO队列。单独的Synchronizer可以定义一个灵活的标准,用来描述线程是否应该允许通过,还是需要等待。用AQS构建Synchronizer会有很多好处。不仅仅是它能极大地减少实现过程中消耗的精力,而且你再也不必像没有使用AQS构建synchronizer时那样,去应付多个竞争点了。使用 AQS构建的synchronizer只可能在一个点上发生阻塞,这样降低了上下文切换的开销,并提高了吞吐量。AQS的设计充分考虑了可伸缩性,所有 java.util. concurrent中构建于AQS 的 synchronizer都会从中获益。
AQS原理:AQS的核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并将共享资源设置为锁定状态,如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是用CLH队列锁实现的,即把暂时获取不到锁的线程加入到队列中。
CLH(Craig,Landin,and Hagersten)队列(FIFO)是一个虚拟的双向队列,虚拟的双向队列即不存在队列实例,仅存在节点之间的关联关系。AQS是将每一条请求共享资源的线程封装成一个CLH锁队列的一个结点(Node),来实现锁的分配。
AQS有以下几个特点:
- 用state(用volatile修饰,初始值为0)属性来表示资源的状态(分独占模式和共享模式),子类需要定义如何维护这个状态,控制如何获取锁和释放锁
- getState -获取state状态
- setState-设置state状态
- compareAndSetState -乐观锁机制设置state状态
- 独占模式是只有一个线程能够访问资源,而共享模式可以允许多个线程访问资源
- 提供了基于FIFO的等待队列,类似于Monitor的 EntryList
- 条件变量来实现等待、唤醒机制,支持多个条件变量,类似于Monitor的 WaitSet
- 子类主要实现这样一些方法(默认抛出UnsupportedOperationException)
- -tryAcquire:独占方式。尝试获取资源,成功则返回true,失败则返回false。
- -tryRelease:独占方式。尝试释放资源,成功则返回true,失败则返回false
- - tryAcquireShared:共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源
- - tryReleaseShared:共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回true,否则返回false。
- - isHeldExclusively:该线程是否正在独占资源。只有用到condition才需要去实现它
AQS就是基于CLH队列,用volatile修饰共享变量state,线程通过CAS去改变状态符,成功则获取锁成功,失败则进入等待队列,等待被唤醒。
有关CLH对象的详细原理如下:(1条消息) AQS的前菜—详解CLH队列锁_fyygree的博客-CSDN博客_clh队列锁



