AQS流程图(v 1.1)
2020-11-18 19:30:16 0 举报
AQS 源码
作者其他创作
大纲/内容
Node:n2thread =t2prev= n1next =null
true
next
tail
head
①表示当前线程抢占锁成功②表示 当前线程和占用的线程是同一个线程(重入锁)锁的状态加1
没有head节点,调用enq()方法,并将node加入到队列
判断头节点的.waitStatus是否小于0
返回node
addWaiter(Node.EXCLUSIVE)
true,执行行图①
lock .lock()
addWait详解er(Node mode)
表示 获取到锁了 1、node 设置为头节点2、释放头节点 3、node移除队列
sync继承AbstractQueuedSynchronizer
阻塞结束
false
在次循环判断
Node:n1thread =nullprev= null next =n2
调用enq()
tryAcquire(arg)
unlock()
整个aqs的核心之一注意: 这里用的for(::) 自旋首先判断node 的前置节点,font color=\"#ff0000\
这个队列表示,在节点n2 插入队列之前,没有其他节点在排队 注意, 当前持有所锁的线程,永远不会处于排队队列中,这是因为: 当前一个线程调用lock 获取锁时,只有两种情况:1)所处于自由状态(state ==0 ) 他不需要排队,通过cas 可以立即获取到锁 2)锁处于非自由状态,线程加入到了排队 队列的队头(不包括head) 等待锁,某一事了 锁被其他县城释放,并唤醒这个排队的线程, 线程唤醒后执行tryAcquire 获取到了锁,然后在重新维护队列,将自己从队列中移除所以 不会出现 占有锁的线程出现 在队列中
abstract void lock();
parkAndCheckInterrupt()线程进入阻塞状态
LockSupport.unpark(s.thread);
③表示线程抢占锁失败 返回false
setExclusiveOwnerThread(null);设置当前null 线程占用
pred.waitStatus== Node.SIGNAL(-1)
prve
在次自旋 执行
这个方法接收两个参数 :参数2 是当前线程node 参数1 是参数2的 前置节点
返回true
判断头节点的下一个节点是否为空 或 判断下一个节点的 waitStatus 值大于0
Node:n2thread =t2prev= n1next =n3
acquireQueued返回 表示线程获到锁,线程逐级返回,加锁过程结束
FairSync()
if (pred != null)
执行排队逻辑
AQS队列(链表)
设置pred.waitStatus = -1
sync.release(1);
Node:n3thread =t3prev= n2next =null
执行park逻辑
return false
acquire(1);
final Node p = node.predecessor();当前线程的 前置节点 是不是头节点
h != null && h.waitStatus != 0头节点不为空 并且 头节点的waitStatus 不等于0
prev
tryAcquire(arg)
unparkSuccessor(h);
acquireQueued()
setState(0);设置当前锁无占用状态
enq(node); ②
tryRelease(1)
公平锁比非公平锁 少一步CAS后续操作都一样
非公平锁
Lock lock = new ReentrantLock(boolean);
final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { font color=\"#ff0000\
public void lock() { sync.lock(); }
private final boolean parkAndCheckInterrupt() { LockSupport.park(this); return Thread.interrupted(); }
acquireQueued详解
解锁
CAS获取锁
公平锁
成功获 取到锁,设置当前线程持有锁 返回
队列已经初始化,将node加入到队尾加入队列后可能如下
pred.waitStatus>0?
收藏
收藏
0 条评论
下一页