ReentrantLock是一个互斥锁,它具有synchronized相同的能力;但相比之下,ReentrantLock扩展性更强,比如实现了公平锁。
下面详细拆解下ReentrantLock的公平锁和非公平锁的实现。
JDK版本:1.8.0_40
先看ReentrantLock两个构造方法:
// 默认非公平
public ReentrantLock() {
sync = new NonfairSync();
}
// 根据传参来实现公平或非公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
因此,要想实现公平锁,只需要传参为true即可。
先来看一个测试类,后面都将围绕该测试类来分享:
public class TestReentrantLock {
private static ReentrantLock lock = new ReentrantLock(true);
public static void main(String[] args) {
Runnable runnable = () -> {
process();
};
Thread t0 = new Thread(runnable);
Thread t1 = new Thread(runnable);
Thread t2 = new Thread(runnable);
t0.start();
t1.start();
t2.start();
}
public static void process() {
String name = Thread.currentThread().getName();
System.out.println(name +" 尝试获取锁");
lock.lock();
try {
System.out.println(name +" 已获取锁");
sleep(1000L);
} finally {
System.out.println(name +" 释放锁");
lock.unlock();
}
}
private static void sleep(Long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
// ignore
}
}
}
输出:
Thread-0 尝试获取锁
Thread-2 尝试获取锁
Thread-1 尝试获取锁
Thread-0 已获取锁
Thread-0 释放锁
Thread-2 已获取锁
Thread-2 释放锁
Thread-1 已获取锁
Thread-1 释放锁
根据这个测试类,通过画图的方式,一起来看看每一步都执行了什么。
先来看看lock()过程
1)首先创建一个公平锁,ReentrantLock lock = new ReentrantLock(true);
2)t0 尝试获取锁,lock.lock(),该方法会调用父类的 acquire 方法