AQS之ReentrantLock
2023-03-12 22:42:49 0 举报
生平不识Doug Lea,学懂并发也枉然 彻底搞懂AQS底层源码 --致敬大师 致敬李二狗
作者其他创作
大纲/内容
因为AQS存在公平与非公平改为0 非公平情况下可能会再次被prak
入队存在竞争;保证所有阻塞线程对象能够被唤醒
AQS三大核心原理 :自旋,LockSupport,CAS,queue队列公平与非公平两种特性exclusiveOwnerThread 当前获取锁的线程是谁!state 状态器queue 同步等待队列(FIFO CLH)
enq(node)
唤醒
false
final Node p = node.predecessor();
Node s = node.next;
tryAcquire(arg)(锁竞争逻辑)
next
改为
setExclusiveOwnerThread(current)exclusiveOwnerThread=当前线程
LockSupport.park(this);return Thread.interrupted();
代表cancel状态
NodeThread=T2
等于0队头,队尾是否一样(队列是空);CAS修改state 0-1
else if (current == getExclusiveOwnerThread()) {
当前线程持有同步器
head=null
waitStatus=0
获取前驱节点信号量
unparkSuccessor(h);
thread=T....
能够获取到,节点出队,并且把head往后挪一个节点,新的头节点就是当前节点
prev
Park阻塞线程唤醒有两种方式:1、中断2、release()
LockSupport.unpark(s.thread);
acquire(int arg)
setHead(node)
compareAndSetHead(new Node())
if (ws == Node.SIGNAL)
setState(c);
tail
NodeThread=null
不等于0线程的引用是否是自己
head
state+1
判断head节点是否为空;信号量!=0
int c = getState()
tryRelease(int releases)
独占:EXCLUSIVE共享:SHARED
thread=null
int ws = pred.waitStatus;
int c = getState() - releases;
释放锁成功
第一次for循环 修改head状态WaitStatus 0- -1
parkAndCheckInterrupt()
唤醒下一个线程
acquireQueued(addWaiter(Node.EXCLUSIVEfont color=\"#323232\
获取队列第一个节点
if (p == head && tryAcquire(arg)) {
NodeThread=T0
null
GC
shouldParkAfterFailedAcquire(Node font color=\"#e74f4c\
thread=Tn
waitStatus(信号量)
pred 前驱节点
acquireQueued(font color=\"#4ccbcd\
节点阻塞之前再尝试一次获取锁
必须初始化一个空的Node节点;(考虑空指针问题)
修改前驱节点WaitStatus 0- -1
。。。。。
lock()
for (;;) {
if (tryRelease(arg)) {
代表节点当前的状态signal(等待被唤醒)
true
waitStatus=-1
if (h != null && h.waitStatus != 0)
release(int arg)
唤醒前驱节点的下一个节点
if (t == null) {
unlock()
阻塞
竞争失败线程入队
获取下一个线程
NodeThread=T1
true重复加锁(state+1+....)
0 条评论
下一页