可重入锁 (ReentrantLock)
ReentrantLock 意思为可重入锁,指的是一个线程能够对一个临界资源重复加锁。为了帮助大家更好地理解ReentrantLock的特性,
我们先将ReentrantLock跟常用的Synchronized进行比较,其特性如下(蓝色部分为本篇文章主要剖析的点):
ReentrantLock有三个内部类, Sync 和 FairSync / NonfairSync 锁
Sync: 基于 AQS 定制的可重入锁的同步控制基础。在下面子类化为公平版本和不公平版本。使用 AQS state 字段表示锁上的保持次数。 FairSync: 基于 Sync 实现的公平锁 NonFairSync: 基于 Sync 实现的不公平锁
Sync:
源码分析
Sync
abstract static class Sync extends AbstractQueuedSynchronizer {
/**
* 尝试加不公平锁
* acquires 加多少次锁
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
// state 代表当前锁被锁的次数
int c = getState();
// 0 代表锁未被使用
if (c == 0) {
// CAS 加锁
if (compareAndSetState(0, acquires)) {
// 设置排它锁
setExclusiveOwnerThread(current);
return true;
}
}
// 如果锁已经被使用了, 但是当前占用锁的是当前线程
else if (current == getExclusiveOwnerThread()) {
// 继续加锁占有锁
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
// 因为当前线程占有锁了, 所以无需用 CAS 来加锁
setState(nextc);
return true;
}
// 锁失败
return false;
}
// 解锁 releases 次
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
// 非当前线程释放锁时抛出异常
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// 释放完锁如果次数为 0, 代表当前线程已经无需占用此锁了
if (c == 0) {
free = true;
// 释放排他锁
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
// 占有锁当前锁的是否是当前线程
protected final boolean isHeldExclusively() {
// While we must in general read state before owner,
// we don't need to do so to check if current thread is owner
return getExclusiveOwnerThread() == Thread.currentThread();
}
// Methods relayed from outer class
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
final boolean isLocked() {
return getState() != 0;
}
}
FairSync
/**
* 基于 Sync 实现的公平锁
*/
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);
}
/**
* 公平锁的 tryAcquire
*/
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;
}
}
NonFairSync
/**
* 基于 Sync 实现的不公平锁
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
// 先 CAS 锁下试试
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
// 参考 Sync 实现
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}