学习三板斧
- 1.理论
- 2.实操
- 3.小总结
一.LOCK
0.阻塞和唤醒线程的方法

1.object中的wait和notify


2.lock中的await和signal

3.lockSupport



二.AQS (抽象队列同步器)


和AQS有关的对外api






共享资源被占用:





AQS内部体系结构



Node类


每个node都存放一个线程

AQS源码解读







案例银行业务
走非公平锁

1.A线程没进入之前

2.A进入之后

3.B即将进入,发现A已经占用了,走else分支


image.png
可重入锁的体现
4.B返回false后取反,继续走其他方法--addWaiter()


B第一次进来 tail尾节点是null,因此 走enq()方法

初始化时,是直接new 一个Node节点 (通过CAS方式)


对应588行代码
注意:因为是
for(;;) 所以,此时还没返回, 此时才走else

(t是哨兵节点)

B成功入队(注意,A获取锁后,B进去等待队列,而等待队列的第一个node不是B而是一个哨兵节点,加入哨兵节点是为了简化操作)
5.C加入队列(由于有B已经在了,所以没进入enq()方法)




-
acquireQueued()分析
image.png

尝试将第一个节点(此时是B)再去获取锁,失败 走else


连续两次尝试都失败后,调用park,挂起等待

当C过来次也是如此

此时 parkAndCheckInterrupt()还未结束,就挂起;
方法描述:


7.A准备离开,调用unlock方法-->会调用sync的realse方法


A释放后,返回true,此时走1261行代码

走unparkSuccessor()

注意图有误:此时B节点的waitStatus = -1,由于C加入的缘故
8.出队
B被唤醒

B抢占成功后走864行



把原来的B变成哨兵节点,且不再引用原先哨兵节点,无引用的哨兵节点将会被GC回收

9.小总结
网友评论