ReentrantLock公平锁和非公平锁(gold_axe)

2020-10-26  本文已影响0人  胖达_4b7e

里面有内部类 继承AQS



AQS里面 提供状态, 几个队列

加锁实际上是调 内部类Sync的lock


区别是:

非公平锁, 直接cas尝试拿锁2次
公平锁首先看有没有线程在排队

公平 | 非公平

acquire() 是AQS里面提供

tryAcquire是模板方法 子类各自实现, 非公平锁是 直接这再试一次, 公平锁是前面没了才试:

公平 | 非公平
可以看到, 就一句不同, 公平是前面没有排队了 才cas, 非公平不看前排队, 直接cas

如果 tryAcquire失败acquireQueued 是AQS方法 对公平非公平都是一样的


↑ 这里会 互斥量 阻塞 park , 和syn重量锁一样
会再试试, 前面是不是head, 是的话 就是刚好轮到我了 不用睡眠了

就是说, 非公平锁 不管怎么样 来了先2次cas抢锁, 都失败才排队

公平锁 为例

1.第一次加锁 t1





这里 head tail 都null , false马上返回, 啥都没做

2.t1没结束, t2来拿锁了(如果t1已经结束, t2如t1)


如果, tryAcquire失败, 就要入队了
注意:
就是说 , 如果 tryAcquire 没失败过, 从来就没冲突, t1 已经结束了, t2才来, 线程们是交替那锁的, AQS里面的双向链表根本不会初始化, 省了! t1 t2 是一样的流程!
入队↓ 会初始化队列


就是
head字段指向head节点(图中的xx, 一个里面没线程的空节点),
tail字段指向 t2产生的节点
注意: addWaiter这里只是加入队列, 排队了 但是么有睡眠

前面么有排队的 , 先 cas一次试试

t1 没好, t2 睡眠排队中, t3来了

前面和t2一样(除了不用队列已经初始化好了,这里只要插入节点 )

这里是直接休眠了, 前面都有节点等着, 不用试了 , 直接park

上一篇下一篇

猜你喜欢

热点阅读