@TOC
抽象队列同步器
CLH队列
CLH(Craig,Landin,and Hagersten)队列是一个虚拟的双向队列,虚拟的双向队列即不存在队列实例,仅存在节点之间的关联关系。
没错 AQS就是基于CLH队列锁实现的。
AQS组成
- state (volatile int)
- exclusiveOwnerThread 持有资源的线程
- FIFO 双向队列
源码
- 模板方法模式
- state访问方法
// 返回同步状态的当前值
protected final int getState() {
return state;
}
// 设置同步状态的值
protected final void setState(int newState) {
state = newState;
}
// CAS操作修改state的值
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
- 方法
isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现它。
tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false。
tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false。
tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
tryReleaseShared(int):共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回true,否则返回false。
ReentrantLock
ReentrantLock lock = new ReentrantLock();
lock.lock(); // 加锁
try {
// 业务逻辑代码
} finally {
lock.unlock(); // 释放锁
}
独占锁与共享锁
独占与共享最大不同就在各自的tryacquire里,对于独占来说只有true或false,只有一个线程得以执行任务;而对于共享锁的tryAcquireShared来说,线程数没达到限制都可以直接执行。
但本质上都是对AQS同步状态的修改,一个是0与1之间,另一个允许更多而已。