队列同步器(AQS)
jdk版本:java11
AQS实现是通过一个int成员变量来表示同步状态,通过内置的FIFO队列来完成线程的等待工作
其实际上是一个双向链表,有tail,head,state
同步器中主要可重写的方法
方法 | 说明 |
---|---|
protected boolean tryAcquire(int arg) | 独占式的获取同步状态 |
protected boolean tryRelease(int arg) | 独占式释放同步状态 |
protected int tryAcquireShared(int arg) | 共享式获取同步状态 |
protected boolean tryReleaseShared(int arg) | 共享式释放同步状态 |
protected boolean isHeldExclusively() | 当前同步器是否被当前线程占用 |
支持独占的AQS应该实现tryAcquire
,tryRlease
,isHeldExclusively
方法;支持共享的AQS应该实现tryAcquireShared
,tryReleaseShared
方法
同步器实现
Node
node主要的属性为next,pre, thread
thread为给节点进入队列时的线程
Acquire和Release
如同以上中acquire(int)
,acquireShared(int)
,release(int)
,releaseShared(int)
则会在其内部调用其对应的try方法
acquire
addwaiter
JDK9的时候提供变量句柄VarHandle的方式对类中的变量进行操作,compareAndSetTail就是通过设置tail的VarHandle,对tail进行操作cas操作
acquireQueue
为了维护FIFO原则,头结点释放同步状态,他的后继节点才能获取去同步状态,同样后继节点被唤醒时,必须检查其前继节点是否为头结点
acquire()执行流程
acquireShared
releaseShared
使用
1、确定访问模式:独占,共享
2、确定资源数:设置状态数量
3、组合自定义同步器:Lock+AQS
官方的例子
独占锁,同一时刻只允许有一个线程获取到锁
class Mutex implements Lock, java.io.Serializable {
// Our internal helper class
private static class Sync extends AbstractQueuedSynchronizer { // Acquires the lock if state is zero
public boolean tryAcquire(int acquires) {
//assert acquires == 1;
// Otherwise unused
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
// Releases the lock by setting state to zero
protected boolean tryRelease(int releases) {
//assert releases == 1;
// Otherwise unused
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
setExclusiveOwnerThread(null);
setState(0);
return true;
}
// Reports whether in locked state
public boolean isLocked() {
return getState() != 0;
}
public boolean isHeldExclusively() {
// a data race, but safe due to out-of-thin-air guarantees
return getExclusiveOwnerThread() ==Thread.currentThread();
}
// Provides a Condition
public Condition newCondition() {
return new ConditionObject();
}
}
// 将操作代理到Sync上
private final Sync sync = new Sync();
public void lock() { sync.acquire(1); }
public boolean tryLock() { return sync.tryAcquire(1); }
public void unlock() { sync.release(1); }
public Condition newCondition() { return sync.newCondition(); }
public boolean isLocked() { return sync.isLocked(); }
public boolean isHeldByCurrentThread() {
return sync.isHeldExclusively();
}
public boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
参考资料
《Java并发编程的艺术》
《Java并发编程实践》