大家好,又见面了,我是你们的朋友全栈君。
原文地址:https://baijiahao.baidu.com/s?id=1594800969528243663&wfr=spider&for=pc
一个关于打水的小故事
话说从前有一个村子,在这个村子中有一口水井,家家户户都需要到这口井里打水喝。由于井水有限,大家只能依次打水。为了实现家家有水喝,户户有水用的目标,村长绞尽脑汁,最终想出了一个比较合理的方案。
首先,在水井边上安排一个看井人,负责维持秩序。
然后,打水时,以家庭为单位,哪个家庭任何人先到井边,就可以先打水,而且如果一个家庭占到了打水权,其家人这时候过来打水不用排队。而那些没有抢占到打水权的人,一个一个挨着在井边排成一队,先到的排在前面。
最后,打水的人打完水以后就告诉看井人,看井人就让等待的队伍中的最前面一个去打水。
这样一来,大家都能打到水,也保证了相对的公平。这就是公平锁的基本思路。
随着时间的推移,村民发现每次去打水的时候都需要排队,想着每次排队都浪费时间,于是就把水桶放在井边代替,自己则溜回家去了。这样一搞,可把看井人累坏,经常往村民家里跑,让他们来打水。于是聪明的看井人想出了一个对策,如果有人打完水后,刚好又有其它人来打水,就直接让这个新来的人上去打水,不用到队伍末尾去排队等候。
这种方式虽然看上去不公平,但是他节省了资源,提高了打水的性能,这就是非公平锁的基本思路。
打水的小故事在java中的应用
Java中可重入锁-ReentrantLock基本上就是按照上面的思路来实现的,我们来对给他们做一个简单的对比。
一次只有一个人能打水 锁需要保证多线程的同步。
必须严格按照排队顺序打水 ReentrantLock提供的公平锁功能。
来得早不如来得巧 ReentrantLock提供的非公平锁功能。
有家人正在打水的时候就不需要排队 ReentrantLock的可重入特性。
那么可重入锁又是怎样实现上面那些特性的呢?
java可重入锁-ReentrantLock实现细节
首先我们从上面的故事入手,看看ReentrantLock中的各个角色都是怎么样的。
打水权 volatile int state
打水者 线程、Thread
打水队伍 双向链表Node
获取锁的时候,公平锁的整个工作流程就如下图所示:
可重入公平锁获取流程
在获取锁的时候,如果当前线程之前已经获取到了锁,就会把state加1,在释放锁的时候会先减1,这样就保证了同一个锁可以被同一个线程获取多次,而不会出现死锁的情况。这就是ReentrantLock的可重入性。
对于非公平锁而言,调用lock方法后,会先尝试抢占锁,在各种判断的时候会先忽略等待队列,如果锁可用,就会直接抢占使用。
释放锁的时候,整个工作流程如下图:
可重入锁释放过程
常见的面试题
说明一下ReentrantLock的原理。
ReentrantLock为什么是可重入的。
公平锁和非公平锁是什么?有什么区别。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/147255.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...