文章字数:734,阅读全文大约需要2分钟
AbstractQueuedSynchronizer
它提供了一种实现阻塞锁和一系列依赖FIFO等待队列的同步器的框架。大部分同步工具内部都是使用AQS
实现的。
一、LockSupport
jdk
提供的线程阻塞、唤醒的工具。同步组件的基础
park
开头的方法是用于阻塞线程的unpark(Thread thread)
方法是解除阻塞的
二、模板方法模式
- 父类使用抽象类,定义若干动作,并且按顺序调用。
- 子类实现具体动作
AQS
里使用了模板方法模式
三、AQS中的抽象模板
3.1独占式获取锁
-accquire
acquireInterruptibly
tryAcquireNanos
3.2共享式获取锁
acquireShared
acquireSharedInterruptibly
tryAcquireShareNanos
3.3独占式释放锁
release
3.4共享式释放锁
releaseShared
3.5子类需要实现的过程方法
tryAcquire
独占获取,内部判断哪个线程拿到了锁,然后setExclusiveOwnerThread(Thread.currentThread())
设置当前线程占有锁,return true
tryRealease
独占释放tryAcquireShare
共享获取tryRealeaseShared
共享释放isHeldExclusively
这个同步器释放处于独占模式(是否占用)
3.6同步状态
state
:字段表示当前同步状态,使用volatile
修饰。getState
:获取setState
:设置当前同步状态compareAndSetState
:使用CAS
设置状态
3.6Condition
AQS
提供了ConditionObject
直接new
返回就行了。- 内部维护了一个等待队列,保存等待的线程
四、AQS公平非共享内部实现
- 内部使用一个先进先出的双向队列保存线程,保存了链表的头和尾
Node
类就是线程节点
节点类型waitState
CANCELLED
线程等待超时或者被中断,需要从队列移走SIGNAL
后续的节点等待状态,当前节点通知后面节点运行CONDITION
等待PEOPGATE
共享状态,表示状态往后面传播0
初始状态
- 竞争锁失败的线程被打包成
Node
放入同步队列尾部(CAS
设置),如果上一个节点是头节点时会尝试获取锁,获取失败阻塞自己。成功会移除头节点,设置自身为头。Realsese
方法会唤醒阻塞。 Condition
中包含一个等待队列