介绍
- java.util.concurrent.locks.AbstractQueuedSynchronizer
- public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable
- 提供一个框架,用于实现依赖于先进先出 (FIFO) 等待队列的阻塞锁和相关同步器(信号量、事件等)
- 此类旨在成为大多数依赖单个原子int值来表示状态的同步器的有用基础。子类必须定义更改此状态的受保护方法,并根据获取或释放此对象来定义该状态的含义。鉴于这些,此类中的其他方法执行所有排队和阻塞机制。子类可以维护其他状态字段,但只有使用方法
getState
、setState
和compareAndSetState
操作的原子更新的 int 值在同步方面被跟踪。 - 子类应定义为非公共内部帮助程序类,用于实现其封闭类的同步属性,参考
java.util.concurrent.locks.ReentrantLock.Sync
- 此类支持默认独占模式和共享模式,通常,实现子类仅支持这些模式中的一种,但两者都可以发挥作用,例如在ReadWriteLock中。仅支持独占或共享模式的子类不需要定义支持未使用模式的方法。
- 这个类定义了一个嵌套的AbstractQueuedSynchronizer.ConditionObject类,它可以被支持独占模式的子类用作Condition实现
- 方法isHeldExclusively报告同步是否相对于当前线程独占地保持
- 用当前getState值调用的方法release完全释放这个object
- 用当前getState值调用的方法acquire ,最终将这个对象恢复到它以前获得的状态
- 要使用此类作为同步器的基础,请重新定义以下方法(如果适用),方法是使用
getState
、setState
或compareAndSetState
检查或修改同步状态:tryAcquire
tryRelease
tryAcquireShared
tryReleaseShared
isHeldExclusively
- 这些方法的实现必须是内部线程安全的,并且通常应该很短并且不会阻塞。定义这些方法是唯一受支持的使用此类的方法。所有其他方法都声明为final方法,因为它们不能独立变化。
- 即使此类基于内部 FIFO 队列,它也不会自动执行 FIFO 获取策略。独占同步的核心采用以下形式
// Acquire: while (!tryAcquire(arg)) { enqueue thread if it is not already queued; possibly block current thread; } // Release: if (tryRelease(arg)) unblock the first queued thread;
- 因为在入队之前调用 acquire 中的检查,所以新获取的线程可能会抢在其他被阻塞和排队的线程之前。但是,如果需要,您可以定义 tryAcquire 和/或 tryAcquireShared 以通过在内部调用一种或多种检查方法来禁用闯入,从而提供公平的FIFO 获取顺序。
- 特别是,大多数公平同步器可以定义tryAcquire以在hasQueuedPredecessors (一种专门为公平同步器使用的方法)返回false时返回true
- 默认 barging(也称为greedy 、 renouncement和convoy-avoidance )策略的吞吐量和可扩展性通常最高。虽然这不能保证公平或无饥饿,但允许较早排队的线程在较晚排队的线程之前重新竞争,并且每次重新竞争都有机会成功对抗传入线程。
- 此类通过将其使用范围专门用于可以依赖int状态、获取和释放参数以及内部 FIFO 等待队列的同步器,部分地为同步提供了高效且可扩展的基础。当这还不够时,您可以使用atomic类、您自己的自定义java.util.Queue类和LockSupport阻塞支持从较低级别构建同步器。
API
protected 方法
protected final
state
- getState
- setState
- compareAndSetState
acquire/release
-
tryAcquire
- 独占锁需要实现
- 尝试以独占模式获取
- 此方法应查询对象的状态是否允许以独占模式获取它,如果允许则获取它
- 可用于实现方法
Lock.tryLock()
-
tryRelease
- 独占锁需要实现
- 尝试设置 state 以反映独占模式下的释放
-
tryAcquireShared
- 共享锁需要实现
- 尝试以共享模式获取
- 此方法应查询对象的状态是否允许以共享模式获取它,如果允许则获取它
-
tryReleaseShared
- 共享锁需要实现
- 尝试设置 state 以反映共享模式下的释放
-
isHeldExclusively
- 判断是否当前线程独占
- 需要子类实现
public 方法
acquire/release
-
acquire
final void acquire(int arg)
- 以独占模式获取
- 忽略中断
- 通过至少调用一次
tryAcquire
并在成功时返回来实现。否则线程会排队,可能会重复阻塞和解除阻塞,调用tryAcquire
直到成功 - 此方法可用于实现方法
Lock.lock
-
acquireInterruptibly
final void acquireInterruptibly(int arg) throws InterruptedException
- 以独占模式获取
- 支持中断
- 通过首先检查中断状态,然后至少调用一次tryAcquire ,成功返回来实现。否则线程将排队,可能会重复阻塞和解除阻塞,调用tryAcquire直到成功或线程被中断
- 此方法可用于实现方法
Lock.lockInterruptibly
-
tryAcquireNanos
final boolean tryAcquireNanos(int arg, long nanosTimeout) throws InterruptedException
- 尝试以独占模式获取
- 支持中断
- 超时返回 false
- 通过首先检查中断状态,然后至少调用一次tryAcquire ,成功返回来实现。否则,线程将排队,可能会重复阻塞和解除阻塞,调用tryAcquire直到成功或线程被中断或超时结束
- 此方法可用于实现方法
Lock.tryLock(long, TimeUnit)
-
release
final boolean release(int arg)
- 以独占模式释放
- 如果tryRelease返回 true,则通过取消阻塞一个或多个线程来实现
- 此方法可用于实现方法
Lock.unlock
-
acquireShared
- 共享模式
- 参考 acquire
-
acquireSharedInterruptibly
- 共享模式
- 参考 acquireInterruptibly
-
tryAcquireSharedNanos
- 共享模式
- 参考 tryAcquireNanos
-
releaseShared
- 共享模式
- 参考 release
queue
- hasQueuedThreads
- 查询是否有任何线程正在等待获取
- hasContended
- 查询是否有线程争用过这个同步器
- 也就是说,如果 acquire 方法曾经被阻塞
- getFirstQueuedThread
- 返回队列中的第一个(等待时间最长的)线程,如果当前没有线程排队,则返回null
- isQueued
- 如果给定线程当前正在排队,则返回 true
- hasQueuedPredecessors
- 查询是否有任何线程等待获取的时间比当前线程长
- getQueueLength
- 返回等待获取的线程数的估计值
- getQueuedThreads
- 返回一个集合,其中包含可能正在等待获取的线程
- getExclusiveQueuedThreads
- 返回一个集合,其中包含可能正在等待以独占模式获取的线程
- 这与
getQueuedThreads
具有相同的属性,只是它只返回那些因独占获取而等待的线程
- getSharedQueuedThreads
- 返回一个集合,其中包含可能正在等待以共享模式获取的线程
- 这与
getQueuedThreads
具有相同的属性,除了它只返回那些由于共享获取而等待的线程
Condition
- owns
final boolean owns(ConditionObject condition)
- 查询入参 ConditionObject 是否使用此同步器作为其锁
- hasWaiters
final boolean hasWaiters(ConditionObject condition)
- 查询是否有任何线程正在等待与此同步器关联的
Condition
- getWaitQueueLength
final int getWaitQueueLength(ConditionObject condition)
- 返回等待与此同步器关联的
Condition
的线程数的估计值
- getWaitingThreads
final Collection<Thread> getWaitingThreads(ConditionObject condition)
- 返回一个集合,其中包含可能正在等待与此同步器关联的
Condition
的那些线程
继承父类 java.util.concurrent.locks.AbstractOwnableSynchronizer
- setExclusiveOwnerThread , getExclusiveOwnerThread
其他
- toString
代码理解
state
定义 volatile 字段 state
private volatile int state;
protected final int getState() {
return state;
}
protected final void setState(int newState) {
state = newState;
}
独占锁和共享锁
通过方法 isHeldExclusively
判断锁是否独占
- 独占,重写方法
tryAcquire
,tryRelease
- 参考
ReentrantLock
- 参考
- 共享,重写方法
tryAcquireShared
,tryReleaseShared
- 参考
ReentrantReadWriteLock
- 参考
Node
private transient volatile Node head;
private transient volatile Node tail;
abstract static class Node {
volatile Node prev;
volatile Node next;
Thread waiter;
volatile int status;
}
Node
在 AQS 内部有三个子类:
ExclusiveNode
SharedNode
ConditionNode
acquire 方法
java.util.concurrent.locks.AbstractQueuedSynchronizer#acquire(java.util.concurrent.locks.AbstractQueuedSynchronizer.Node, int, boolean, boolean, boolean, long)
入参:
- Node node
- 除非重新获取 Condition ,否则为空
- int arg
- 获取参数
- boolean shared
- 是否共享锁模式
- boolean interruptible
- 是否支持中断
- boolean timed
- 是否支持超时
- long time
- 超时时长,单位 ns
返回值:如果获取成功则为正,如果超时则为 0,如果中断则为负
方法的主要逻辑是一个无限循环,直到获取成功、超时或中断。在循环中,它会执行以下操作:
- 检查节点是否是第一个节点。如果是,则确保头节点稳定;否则,确保有效的前驱节点。
- 如果节点是第一个节点或尚未入队,尝试获取。
- 如果节点尚未创建,创建它。
- 如果尚未入队,尝试入队一次。
- 如果从 park 中唤醒,重试(最多 postSpins 次)。
- 如果 WAITING 状态未设置,设置并重试。
- 否则,park 并清除 WAITING 状态,并检查取消。
持有锁的线程不在队列中
队列的第一个 Node 的 thread 是 null
park 阻塞线程
LockSupport.park(this);
然后在 release 方法中 unpark 后,继续执行 acquire 方法的下一个语句
return cancelAcquire(node, interrupted, interruptible);
在 cancelAcquire 方法中对 Node 队列进行操作
这里不是在 release 方法中对 Node 队列进行操作,感觉有点反常识,确实精彩
- AbstractQueuedSynchronizer concurrent 20230608 locks javaabstractqueuedsynchronizer concurrent 20230608 concurrent condition 20230608 locks locksupport concurrent 20230608 locks reentrantlock concurrent 20230608 locks concurrent 20230607 locks java concurrent java util completablefuture concurrent 20230618 java executorservice concurrent 20230713 java rejectedexecutionexception concurrent java util java线程concurrent工具