文章字数:734,阅读全文大约需要2分钟
AbstractQueuedSynchronizer它提供了一种实现阻塞锁和一系列依赖FIFO等待队列的同步器的框架。大部分同步工具内部都是使用AQS实现的。
一、LockSupport
jdk提供的线程阻塞、唤醒的工具。同步组件的基础
park开头的方法是用于阻塞线程的unpark(Thread thread)方法是解除阻塞的
二、模板方法模式
- 父类使用抽象类,定义若干动作,并且按顺序调用。
- 子类实现具体动作
AQS里使用了模板方法模式
三、AQS中的抽象模板
3.1独占式获取锁
-accquire
acquireInterruptiblytryAcquireNanos3.2共享式获取锁
acquireSharedacquireSharedInterruptiblytryAcquireShareNanos3.3独占式释放锁
release
3.4共享式释放锁
releaseShared
3.5子类需要实现的过程方法
tryAcquire独占获取,内部判断哪个线程拿到了锁,然后setExclusiveOwnerThread(Thread.currentThread())设置当前线程占有锁,return truetryRealease独占释放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中包含一个等待队列