目录
简介
同步队列器(AQS)负责管理同步容器类中的状态,它管理了一个整数状态信息,可以通过getState()
,setState()
以及compareAndSetState()
等方法,进行操作.这个整数可以表示任意状态.
- reentrantLock用它表示所有线程已经重复获取该锁的次数.
- Semaphore用它表示剩余许可的数量
- FutureTask表示任务状态.
AQS的管理同步状态的同步队列
- 当线程获取同步状态失败时,将当前线程以及等待状态信息构造成一个Node节点,将其加入到同步队列尾部,阻塞该线程.
- 当同步状态被释放,唤醒同步队列的首节点线程,获取同步状态.
重要的方法
可重写的方法
方法名 | 描述 |
---|---|
protected boolean tryAcquire(int arg) | 独占式获取同步状态 |
protected boolean tryRelease(int arg) | 独占式释放同步状态 |
protected int tryAcquireShared(int arg) | 共享式获取同步状态,>=0成功,反之失败 |
protected boolean tryReleaseShared(int arg) | 共享式 释放同步状态 |
protected boolean isHeldExclusively() | 当前同步器是否在独占式下被线程使用,一般该方法表示是否被当前线程所独占 |
同步状态的相关方法
方法名 | 描述 |
---|---|
getState() | 获取当前同步状态 |
setState() | 设置当前同步状态 |
compareAndSetState(int expect, int update) | 使用cas设置同步状态,该方法保证同步状态设置的原子性 |
源码浅析
简介
AQS,等待队列是一种CLH queue
的变体。
CLH 通常用于自旋锁。用来代替使用阻塞同步。
每个节点有个status字段,跟踪现场是否阻塞,当他的前驱节点释放锁,status为SIGNAL
。
队列中的每个节点,也作为一个持有单一等待线程的特定监视器
状态字段不控制(线程)是否持有锁
队头元素会尝试获取锁,但是不一定会成功。
进入CLH 锁队列,将原子性的进入队尾,出队,只需要更新头节点,然后确定有效的后继节点。
- prev主要处理
CANCELLED
节点 - next用来实现阻塞机制.前继节点通过遍历可以确定哪个线程(node持有线程id),然后通知节点唤醒.
CLH队列需要一个虚拟的头节点才能开始(懒加载模式创建)
条件队列(condition
)使用相同的节点,但是其实现需要一个简单(非并行)的队列,只有在专用时访问,等待将节点插入条件队列.收到信号,将条件队列中的节点转移至主队列.
node
1 | // 双向链表 |
独占式加锁
1 |
|
独占式释放锁
1 | public final boolean release(int arg) { |