点赞再看,养成习惯,微信搜索【三太子敖丙】关注这个互联网苟且偷生的工具人。git
本文 GitHub github.com/JavaFamily 已收录,有一线大厂面试完整考点、资料以及个人系列文章。github
上次咱们提到了乐观锁和悲观锁,那咱们知道锁的类型还有不少种,咱们今天简单聊一下,公平锁和非公平锁两口子,以及他们在咱们代码中的实践。web
开始聊以前,我先大概说一下他们二者的定义,帮你们回顾或者认识一下。面试
公平锁:多个线程按照申请锁的顺序去得到锁,线程会直接进入队列去排队,永远都是队列的第一位才能获得锁。sql
非公平锁:多个线程去获取锁的时候,会直接去尝试获取,获取不到,再去进入等待队列,若是能获取到,就直接获取到锁。微信
我举个例子给他家通俗易懂的讲一下的,想了好几天终于在前天跟三歪去肯德基买早餐排队的时候发现了怎么举例了。app
如今是早餐时间,敖丙想去kfc搞个早餐,发现有不少人了,一过去没多想,就乖乖到队尾排队,这样你们都以为很公平,先到先得,因此这是公平锁咯。工具
那非公平锁就是,敖丙过去买早餐,发现你们都在排队,可是敖丙这我的有点渣的,就是喜欢插队,那他就直接怼到第一位那去,后面的鸡蛋,米豆都不行,我插队也不敢说什么,只能默默忍受了。spa
可是偶尔,鸡蛋也会崛起,叫我滚到后面排队,我也是欺软怕硬,默默到后面排队,就插队失败了。线程
介绍完简单的例子,你们可能会说,渣丙,这个我也知道的啊。
咱们是否是应该回归真正的实现了,其实在你们常用的ReentrantLock中就有相关公平锁,非公平锁的实现了。
你们还记得我在乐观锁、悲观锁章节提到的Sync类么,是ReentrantLock他自己的一个内部类,他继承了AbstractQueuedSynchronizer,咱们在操做锁的大部分操做,都是Sync自己去实现的。
Sync呢又分别有两个子类:FairSync和NofairSync
他们子类的名字就能够见名知意了,公平和不公平那又是怎么在代码层面体现的呢?
公平锁:
你能够看到,他加了一个hasQueuedPredecessors的判断,那他判断里面有些什么玩意呢?
代码的大概意思也是判断当前的线程是否是位于同步队列的首位,是就是返回true,否就返回false。
我总以为写到这里就应该差很少了,可是我坐下来,静静的思考以后发现,仍是差了点什么。
上次聊过ReentrantLock了,可是AQS什么的我都只是提了一嘴,一个线程进来,他整个处理链路究竟是怎样的呢?
公平锁到底公平不公平呢?让咱们一块儿跟着丙丙走进ReentrantLock的心里世界。
上面提了这么多,我想你应该是有所了解了,那一个线程进来ReentrantLock这个渣男是怎么不公平的呢?(默认是非公平锁)
我先画个图,帮助你们了解下细节:
ReentrantLock的Sync继承了AbstractQueuedSynchronizer也就是咱们常说的AQS
他也是ReentrantLock加锁释放锁的核心,大体的内容我以前一期提到了,我就不过多赘述了,他们看看一次加锁的过程吧。
A线程准备进去获取锁,首先判断了一下state状态,发现是0,因此能够CAS成功,而且修改了当前持有锁的线程为本身。
这个时候B线程也过来了,也是一上来先去判断了一下state状态,发现是1,那就CAS失败了,真晦气,只能乖乖去等待队列,等着唤醒了,先去睡一觉吧。
A持有久了,也有点腻了,准备释放掉锁,给别的仔一个机会,因此改了state状态,抹掉了持有锁线程的痕迹,准备去叫醒B。
这个时候有个带绿帽子的仔C过来了,发现state怎么是0啊,果断CAS修改成1,还修改了当前持有锁的线程为本身。
B线程被A叫醒准备去获取锁,发现state竟然是1,CAS就失败了,只能失落的继续回去等待队列,路线还不忘骂A渣男,怎么骗本身,欺骗个人感情。
诺以上就是一个非公平锁的线程,这样的状况就有可能像B这样的线程长时间没法获得资源,优势就是可能有的线程减小了等待时间,提升了利用率。
如今都是默认非公平了,想要公平就得给构造器传值true。
ReentrantLock lock = new ReentrantLock(true);
复制代码
说完非公平,那我也说一下公平的过程吧:
线A如今想要得到锁,先去判断下state,发现也是0,去看了看队列,本身竟然是第一位,果断修改了持有线程为本身。
线程b过来了,去判断一下state,嗯哼?竟然是state=1,那cas就失败了呀,因此只能乖乖去排队了。
线程A暖男来了,持有没多久就释放了,改掉了全部的状态就去唤醒线程B了,这个时候线程C进来了,可是他先判断了下state发现是0,觉得有戏,而后去看了看队列,发现前面有人了,做为新时代的良好市民,果断排队去了。
线程B获得A的召唤,去判断state了,发现值为0,本身也是队列的第一位,那很香呀,能够获得了。
总结我不说话了,可是去获取锁判断的源码,箭头所指的位置,如今是否是都被我合理的解释了,当前线程,state,是不是0,是不是当前线程等等,都去思考下。
鬼知道我为了画图,画了多少费稿,点个赞过度么?
公平锁真的公平么?那什么层面不是绝对的公平,什么层面才能算公平?
我是敖丙,一个在互联网苟且偷生的工具人。
最好的关系是互相成就,各位的「三连」就是丙丙创做的最大动力,咱们下期见!
文章持续更新,能够微信搜索「 三太子敖丙 」第一时间阅读,回复【资料】【面试】【简历】有我准备的一线大厂面试资料和简历模板,本文 GitHub github.com/JavaFamily 已经收录,有大厂面试完整考点,欢迎Star。