AQS框架
2021-02-26 17:45:26 40 举报
AQS框架流程解析
作者其他创作
大纲/内容
ReentrantLock有个Sync的静态抽象类,内部的FairSync/NonfairSync继承了Sync,让ReentrantLock可以在构造方法中给sync属性赋公平锁和非公平锁,默认是非公平锁
thread = nullprev next
ReentrantLock
Sync sync;sync.lock();
true
1
程序阻塞在这里后将,等待其他线程释放锁(将state改为0,并unpark当前线程来唤醒),继续走accquireQueued方法中的死循环来替换傀儡节点,执行线程
3
shouldParkAfterFailedAcquire
N
next
tryRelease(1)
2:CAS
null
thread 2
Sync extend AQS
lock()
线程1排队结果
prev
尾节点为空,即这是第一个排队的线程
state = 1 execlusiveOwnerThread = thread 0
addWaiter.enq(node)
Y
&&
head tail
lock.lock()
1循环
ws = 0
当前线程是第一个进入双向链表的线程,需要完成FIFO双向链表的初始化工作;取到尾节点tail如果尾节点还是为null 创建一个空节点new Node()并赋给尾节点进入第二次for循环,此时尾指针不为null,进入else代码块 当前节点的前节点指向尾节点 调用compareAndSetTail来将尾节点改为当前节点 成功则将前尾节点next指向当前节点 返回当前节点
2
ws = -1
!tryAcquire(1)
thread = t2prev next
unparkSuccessor(h)
第一个进入队列的线程的阻塞场景参数node 为t1节点node,arg = 1在for循环里面取得傀儡结点p;判断 p == head表示是第一个排队的->尝试获取锁(非公平锁和公平锁的tryAcquire方法不一样),公平锁多了个!hasQueuedPredecessors() && ; 可以获取锁则将t1的node设为头节点并将p.next = null来help gc 并 return false否则走第二及往后节点走的流程
thread = t1prev next
2循环
thread 0
唤醒节点的处理器参数:傀儡节点 h1.拿到傀儡节点的ws状态值-1;2.判断ws < 0 ? CAS设置ws的值为0;3.拿到傀儡节点的下一个节点 s;4.判断 s == null 或者 s.waitStatus > 0,???不知道什么意思......5.如果s != null,LockSupport.unpark(s.thread)唤醒线程;
selfInterrupt()
thread 1
state已经改为0了,阻塞的线程被唤醒,回到accquireQueued的死循环加锁的流程
pred
Sync sync;sync.release(1);
CAS修改state值成功,即占有锁成功,设置占有线程属性
第二个及往后进入队列的线程的阻塞场景shouldParkAfterFailedAcquire:在尝试获取锁后应该阻塞线程吗?参数:前节点,当前节点ws == -1 return true,表示应该park当前node线程
AQS(Abstract Queue Synchronizor,抽象队列同步器)框架:通过一个volatile修饰的state来表示同步的状态,使用内置的一个FIFO队列来完成抢占资源的排队状态,把每个来抢占资源的线程封装成一个双向链表的节点,各线程通过CAS来修改state的值。整个过程都围绕着自旋锁、CAS和park/unpark来实现的。
链表的tail不为空
第二个及往后进入队列的线程的阻塞场景shouldParkAfterFailedAcquire:在尝试获取锁后应该阻塞线程吗?参数:前节点,当前节点将前节点的ws改为-1,return false,进入第二次循环
AbstractQuequSynchronizer
acquired(1)
unlock
addWaiter(Node.EXCLUSIVE)
第一个进入队列的线程的阻塞场景参数node 为t1节点node,arg = 1在for循环里面取得傀儡结点p;判断 p == head表示是第一个排队的->尝试获取锁; 可以获取锁则将t1的node设为头节点并将p.next = null来help gc 并 return false否则走第二及往后节点走的流程
将当前线程封装成一个Node渠道尾节点 pred = tail如果pred != null,说明已经有排队的节点在排队了将当前节点的prev指向尾节点调用compareAndSetTail来将尾巴节点改为当前节点成功则前尾节点的next指向当前节点,返回当前节点
parkAndCheckInterrupt:park线程并检查中断park:调用LockSupport.park(this),将线程阻塞
release(1)
线程2排队结果
enq(node)
nonfairTryAcquire(1)
链表的tail不为空->2循环
rerurn false
在addWaiter方法执行将线程节点入队后需要将节点线程阻塞
将线程节点入队
h != null &&h.waitStatus != 0
2循环:CAS
addWaiter(node)
0 条评论
回复 删除
下一页