ReentrantLock源码剖析
ReentrantLock源码剖析
测试案例:
public class ReentrantLockDemo {
// ReentrantLock lock = new ReentrantLock(); // 默认是非公平锁
// ReentrantLock lock = new ReentrantLock(true); // true:公平锁,false:非公平锁
public static void main(String[] args) {
new ReentrantLockDemo().exe();
}
public void exe() {
Thread thread1 = new Thread(this::meal, "小 A");
Thread thread2 = new Thread(this::meal, "小 B");
Thread thread3 = new Thread(this::meal, "小 C");
System.out.println("小 A 排队打餐");
System.out.println("小 B 排队打餐");
System.out.println("小 C 排队打餐");
thread1.start();
thread2.start();
thread3.start();
}
public void meal() {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + " --> 开始打餐");
System.out.println(Thread.currentThread().getName() + " --> 打餐中。。。");
System.out.println(Thread.currentThread().getName() + " --> 打完餐,离开");
} finally {
lock.unlock();
}
}
// private void sleep() {
// try {
// TimeUnit.SECONDS.sleep(1);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
}
非公平锁运行结果:
小 A 排队打餐
小 B 排队打餐
小 C 排队打餐
小 A --> 开始打餐
小 A --> 打餐中。。。
小 A --> 打完餐,离开
小 C --> 开始打餐
小 C --> 打餐中。。。
小 C --> 打完餐,离开
小 B --> 开始打餐
小 B --> 打餐中。。。
小 B --> 打完餐,离开
公平锁运行结果:
小 A 排队打餐
小 B 排队打餐
小 C 排队打餐
小 A --> 开始打餐
小 A --> 打餐中。。。
小 A --> 打完餐,离开
小 B --> 开始打餐
小 B --> 打餐中。。。
小 B --> 打完餐,离开
小 C --> 开始打餐
小 C --> 打餐中。。。
小 C --> 打完餐,离开
源码剖析:
ReentrantLock底层基于AQS
// true: 公平锁,false:非公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
公平锁和非公平锁的底层实现逻辑:
主要在获取锁:
java.util.concurrent.locks.ReentrantLock.FairSync#lock
// 公平锁
final void lock() {
// 调⽤ AQS 的 acquire 排队等待获取锁,⼊参是 1
// 说白了就是一上来先排队
acquire(1);
}
java.util.concurrent.locks.ReentrantLock.NonfairSync#lock
// 非公平锁
final void lock() {
// ⾸先⽴即尝试CAS获取锁
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
// 调⽤ AQS 的 acquire 排队等待获取锁,⼊参是 1
// 如果没有获取到锁,就老老实实的排队
acquire(1);
}
底层操作的是state变量,state=0表示无锁状态,state!=0表示锁没有完全释放。