ReentrantLock中的公平锁和⾮公平锁的底层实现
公平锁:多个线程按照
申请锁的顺序去获得锁
,线程会直接进入队列去排队,永远都是队列的第一位
才能得到锁。
非公平锁:多个线程去获取锁的时候,会
直接去尝试获取
,获取不到,再去进入等待队列
,如果能获取到,就直接获取到锁。
-
⾸先不管是公平锁和⾮公平锁,它们的底层实现都会使⽤AQS来进⾏排队
- 公平锁和⾮公平锁都是进入的同一个队列
-
它们的区别在于:线程在使⽤lock()⽅法加锁时
-
如果是公平锁,会先检查
AQS队列
中是否存在线程在排队- 检查是否有线程在排队,有则当前线程也进⾏排队
- 如果是⾮公平锁,则不会去检查是否有线程在排队,⽽是直接竞争锁。
- 检查是否有线程在排队,也是检测的同一个队列
-
不管是公平锁还是⾮公平锁,⼀旦
没竞争到锁
,都会进⾏排队 -
当锁释放时,都是唤醒排在最前⾯的线程
- 队列的
先进先出原则
- 队列的
-
所以⾮公平锁只是体现在了
线程加锁阶段
,⽽没有体现在线程被唤醒阶段
。- 体现在第一次获取锁的时候,第一次竞争失败后加入队列了就都是一样的了
-
另外,
ReentrantLock是可重⼊锁
,不管是公平锁还是⾮公平锁都是可重⼊的。//默认非公平 private ReentrantLock lock = new ReentrantLock(); //加true是公平锁 private ReentrantLock lock = new ReentrantLock(true);
-
可重入就是说某个线程
已经获得某个锁
,可以再次获取锁而不会出现死锁
- ReentrantLock和synchronized都是可重⼊锁
-
简单理解就是:
-
如果你
拿到了锁1
,接下来代码块又要拿一次锁1
,你之前已经拿过锁1了,下面的也可以拿到synchronized (this) { System.out.println("第1次,锁是:" + this); //嵌套锁1 -> 此时是可以重复获得的,这就是可重入 synchronized (this) { System.out.println("第2次,锁是:" + this); } }
-