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
