AQS(AbstractQueuedSynchronizer)
2022-03-29 09:24:19 15 举报
AI智能生成
AQS
作者其他创作
大纲/内容
AQS定义两种资源共享方式:Exclusive(独占,只有一个线程能执行,如ReentrantLock)和Share(共享,多个线程可同时执行,如Semaphore/CountDownLatch)
变量
transient volatile Node head
waiter队列的头,刚开始时是一个啥都没有的结点,后面解锁一个去掉一个
transient volatile Node tail
waiter队列的尾,第一次上锁没锁上的往后边插,每当一个倒霉蛋没有获得锁,就加入队列
volatile int state
不同的自定义同步器争用共享资源的方式也不同。自定义同步器在实现时只需要实现共享资源state的获取与释放方式即可
方法(未具体实现,只抛异常)
tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false
tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false
tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源
tryReleaseShared(int):共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回true,否则返回false
方法(已实现)
acquire(int)
tryAcquire()尝试直接去获取资源,如果成功则直接返回(这里体现了非公平锁,每个线程获取锁时会尝试直接抢占加塞一次,而CLH队列中可能还有别的线程在等待);
addWaiter()将该线程加入等待队列的尾部,并标记为独占模式;
acquireQueued()使线程阻塞在等待队列中获取资源,一直获取到资源后才返回。如果在整个等待过程中被中断过,则返回true,否则返回false。(自旋)
如果线程在等待过程中被中断过,它是不响应的。只是获取资源后才再进行自我中断selfInterrupt(),将中断补上。
release(int)
tryRelease(int),tryRelease()都会成功的,因为这是独占模式,该线程来释放资源,那么它肯定已经拿到独占资源了,直接减掉相应量的资源即可(state-=arg),也不需要考虑线程安全的问题。release是根据tryRelease()的返回值来判断线程是否已经完成资源释放。所以实现时,(state=0),要返回true,否则返回false。
unparkSuccessor(Node)
用LockSupport.unpark()方法唤醒队列中最欠扁的那个未放弃的线程。一般来说当前结点的后一个结点就是下一个,但是也可能后面的结点放弃了,这时从尾巴一直往前找,找到第一个能跑的就让他跑
内部类
Node
变量
volatile Node prev
前驱
volatile Node next
后继
volatile int waitStatus
CANCELLED = 1
:表示当前结点已取消调度。当timeout或被中断(响应中断的情况下),会触发变更为此状态,进入该状态后的结点将不会再变化。
默认值0
新节点入队时默认状态
SIGNAL = -1
后继结点在等待当前结点唤醒,后记结点入队时,会将前驱结点更新未SIGNAL
CONDITION = -2
表示结点等待在Condition上,当其他线程调用了Condition的signal()方法后CONDITION状态的结点将从等待队列转移到同步队列中,等待获取同步锁
PROPAGATE = -3
共享模式下,前继结点不仅会唤醒其后继结点,同时也可能会唤醒后继的后继结点。
Node nextWaiter
volatile Thread thread
抢锁的线程
ConditionObject
0 条评论
下一页