文章目录
- ReentrantLock是什么?
- ReentrantLock底层源码:
- ReentrantLock底层原理图解:(以NonfairSync举例)
ReentrantLock是什么?
synchronized关键字是一种隐式锁,即它的加锁与释放是自动的,无需我们关心。而ReentrantLock
是一种显式锁
,需要我们手动编写加锁和释放锁的代码。
相对于synchronized它具备以下特点:
- 可中断
- 可以设置超时时间
- 可以设置公平锁
- 支持多个条件变量
- 与synchronized一样,都支持重入(
同一线程
)
例如:手动枷锁和解锁
注意被ReentrantLock加锁区域必须用
try代码块包裹
,且释放锁需要在finally中来避免死锁。执行几次加锁,就需要几次释放锁。
ReentrantLock底层源码:
点进去ReentrantLock的源码可以看到:
ReentrantLock实现了Lock接口
public interface Lock {
// 获取锁
void lock();
// 获取可中断锁,即在拿锁过程中可中断,synchronized是不可中断锁。
void lockInterruptibly() throws InterruptedException;
// 尝试获取锁,成功返回true,失败返回false
boolean tryLock();
// 在给定时间内尝试获取锁,成功返回true,失败返回false
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
// 释放锁
void unlock();
// 等待与唤醒机制
Condition newCondition();
}
在Lock中定义了多个获取锁的方法
,以及释放锁的方法
。同时还有一个与等待与唤醒机制
有关系的newCondition方法
。
继续往下看Sync类是继承了AQS类(抽象队列同步器
)的
ReentrantLock底层原理图解:(以NonfairSync举例)
- exclusiveOwnerThread 表示
独占当前锁的线程
- head与tail 分别表示了
等待线程队列
的头结点和尾结点; - state 表示同步的状态,为
0时表示未加锁状态
,而大于0时表示加锁状态
。
- 线程来抢锁后使用cas的方式修改state状态,修改状态成功为1,则让exclusiveOwnerThread属性指向当前线程,获取锁成功
- 假如修改状态失败,则会进入双向队列中等待,head指向双向队列头部,tail指向双向队列尾部
- 当exclusiveOwnerThread为null的时候,则会唤醒在双向队列中等待的线程公平锁则体现在按照先后顺序获取锁,非公平体现在不在排队的线程也可以抢锁