以前的博客:详解 ReentrantLock
ReentrantLock的源码非常简单,它通过内部类实现了AQS框架,Lock接口的实现仅仅是对AQS的api的简单封装。
主要也就是ReentrantLock同步语义的学习:
1. 重入性的实现原理;
2. 公平锁和非公平锁。(默认实现:非公平锁)
一、重入性的实现原理
要想支持重入性,就要解决两个问题:
1. 在线程获取锁的时候,如果已经获取锁的线程是当前线程的话则直接再次获取成功;
2. 由于锁会被获取n次,那么只有锁在被释放同样的n次之后,该锁才算是完全释放成功。
通过AQS的学习,我们知道,同步组件主要是通过重写AQS的几个protected方法来表达自己的同步语义。
ReentrantLock的实现,以非公平锁为例,
- 获取锁:核心方法为nonfairTryAcquire:
- 释放锁:tryRelease
公平锁:tryAcqurire:
逻辑与nonfairTryAcquire基本上一直,唯一的不同在于增加了hasQueuedPredecessors的逻辑判断,方法名就可知道该方法用来判断当前节点在同步队列中是否有前驱节点的判断;
如果有前驱节点说明有线程比当前线程更早的请求资源,根据公平性,当前线程请求资源失败;
如果当前节点没有前驱节点的话,再才有做后面的逻辑判断的必要性。公平锁每次都是从同步队列中的第一个节点获取到锁,而非公平性锁则不一定,有可能刚释放锁的线程能再次获取到锁。
二、公平锁和非公平锁。
1、公平锁每次获取到锁为同步队列中的第一个节点,保证请求资源时间上的绝对顺序,而非公平锁有可能刚释放锁的线程下次继续获取该锁,则有可能导致其他线程永远无法获取到锁,造成“饥饿”现象。
2、公平锁为了保证时间上的绝对顺序,需要频繁的上下文切换,而非公平锁会降低一定的上下文切换,降低性能开销。因此,ReentrantLock默认选择的是非公平锁,则是为了减少一部分上下文切换,保证了系统更大的吞吐量。