ReentrantLock源码详解
1. 首先先看ReentrantLock的构造器
public class ReentrantLock {
public ReentrantLock() {
// 默认的构造器就是非公平锁
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
// 可以通过入参来构造是公平的还是非公平的
sync = fair ? new FairSync() : new NonfairSync();
}
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
try{
lock.lock();
// do something;
} finally{
lock.release();
}
}
}
2. NofairSync类
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
final void lock() {
// 第一次尝试以非公平的方式获取锁
if (compareAndSetState(0, 1))
// 线程通过CAS来获取锁,如果当前锁的状态是0(代表此时锁还没有被其他线程占有),那么该锁将被该线程独占
setExclusiveOwnerThread(Thread.currentThread());
else
// 如果通过CAS来获取锁,如果当前锁的状态是1,则调用父类(AbstractQueuedSynchronizer)的acquire方法。
// 而父类的acquire方法则会调用由子类实现的tryAcquire方法。
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
abstract void lock();
final boolean nonfairTryAcquire(int acquires) {
// 获取当前线程
final Thread current = Thread.currentThread();
// 获取当前同步器的状态,如果c为0表示未上锁
int c = getState();
if (c == 0) {
// 第二次尝试以非公平的方式获取锁
// 通过CAS的原子操作将同步器的状态设置为acquires.
if (compareAndSetState(0, acquires)) {
// 如果设置成功,那么当前线程将独占该锁。
setExclusiveOwnerThread(current);
return true;
}
}
// 重入锁实现的原理: 如果是当前线程独占了锁
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
// 最大可重入的次数为Integer.MAX_VALUE,如果再加1则会溢出
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
// 设置重入锁的次数
setState(nextc);
return true;
}
return false;
}
/**
* 释放锁
*/
protected final boolean tryRelease(int releases) {
// 由于reentrantLock是可重入的,所以只有在同步器的状态为0时才能释放锁
int c = getState() - releases;
// 只有持有锁的线程才能进行release,不然会报错哦
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
// 将占用锁的线程设置为null
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
}
3. 非公平锁竞争锁的过程
- 插队成功的情况
- 插队失败的情况
4. FairSync类
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);
}
/**
* 公平锁模式下获取锁
*/
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 公平锁与非公平锁只相差这一行代码
// 线程获取锁时会查看该线程是否与首个节点的线程是否相同,如果相同则可以获取锁,不然的只能老老实实排队
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}