ReentrantLock源码概览
AbstractQueuedSynchronizer
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
private transient volatile Node head;
private transient volatile Node tail;
private volatile int state;
}
Node
static final class Node {
static final Node SHARED = new Node();
static final Node EXCLUSIVE = null;
static final int CANCELLED = 1;
static final int SIGNAL = -1;
static final int CONDITION = -2;
static final int PROPAGATE = -3;
volatile int waitStatus;
volatile Node prev;
volatile Node next;
volatile Thread thread;
Node nextWaiter;
final boolean isShared() {
return nextWaiter == SHARED;
}
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
Node() {
}
//构建同步队列上的Node Used by addWaiter
Node(Thread thread, Node mode) {
this.nextWaiter = mode;
this.thread = thread;
}
//构建等待队列上的Node Used by Condition
Node(Thread thread, int waitStatus) {
this.waitStatus = waitStatus;
this.thread = thread;
}
}
Node等待状态waitStatus
Node结点是对每一个等待获取资源的线程的封装,其包含了需要同步的线程本身及其等待状态,如是否被阻塞、是否等待唤醒、是否已经被取消等。
变量waitStatus则表示当前Node结点的等待状态,共有5种取值CANCELLED、SIGNAL、CONDITION、PROPAGATE、0。
- CANCELLED(1):表示当前结点已取消调度。当timeout或被中断(响应中断的情况下),会触发变更为此状态,进入该状态后的结点将不会再变化。
- SIGNAL(-1):表示后继结点在等待当前结点唤醒。后继结点入队时,会将前继结点的状态更新为SIGNAL。
- CONDITION(-2):表示结点等待在Condition上,当其他线程调用了Condition的signal()方法后,CONDITION状态的结点将从等待队列转移到同步队列中,等待获取同步锁。
- PROPAGATE(-3):共享模式下,前继结点不仅会唤醒其后继结点,同时也可能会唤醒后继的后继结点。
- 0:新结点入队时的默认状态。创建node时的默认状态
//线程已经被取消
static final int CANCELLED = 1;
//线程需要去被唤醒
static final int SIGNAL = -1;
//线程正在唤醒等待条件
static final int CONDITION = -2;
//线程的共享锁应该被无条件传播
static final int PROPAGATE = -3;
负值表示结点处于有效等待状态,而正值表示结点已被取消。
所以源码中很多地方用>0、<0来判断结点的状态是否正常,0是新结点入队时的默认状态。
Node指针
同步队列是双向。
volatile Node prev;//同步队列中节点的前置节点
volatile Node next;//同步队列中节点的后置节点
等待队列是单向
Node nextWaiter;//等待队列中节点的后置节点
ReentrantLock
ReentrantLock持有1个Sync实例
public class ReentrantLock implements Lock, java.io.Serializable {
//同步器
private final Sync sync;
//省略代码
}
构造方法
其实是构造1个具体的同步器,默认是非公平锁。
public ReentrantLock() {
//同步器 Sync extends AbstractQueuedSynchronizer
//有2个实现类
//static final class NonfairSync extends Sync
//static final class FairSync extends Sync
sync = new NonfairSync();
}
指定公平锁还是非公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
Sync
Sync继承自AbstractQueuedSynchronizer
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();
int c = getState();
if (c == 0) {
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");
setState(nextc);
return true;
}
return false;
}
//尝试释放锁
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
//是否是持有锁的独占者
protected final boolean isHeldExclusively() {
return getExclusiveOwnerThread() == Thread.currentThread();
}
//条件变量
final ConditionObject newCondition() {
return new ConditionObject();
}
//获取当前持有锁的线程
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
//重入次数
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
//是否加锁
final boolean isLocked() {
return getState() != 0;
}
//反序列化
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}
NonfairSync
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
//加锁方法
final void lock() {
//非公平的体现:上来就立刻做一次cas
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
//尝试加锁方法
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
ReentrantLock加锁的方法是调用同步器的lock方法
public void lock() {
sync.lock();
}
思考:但是在NonfairSync只看到了加锁方法,解锁方法在哪呢? 解锁的方法在父类Sync中
public void unlock() {
sync.release(1);
}
release方法来自AbstractQueuedSynchronizer#release
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
ReentrantLock.Sync#tryRelease
一看就是典型的模板模式
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
但是为什么要这么实现呢?
个人猜测是因为公平锁和非公平锁的加锁的流程是不同的,所以需要把加锁代码分别写在2个实现类里。
但是对于解锁来说,不管是公平锁还是非公平锁,流程是一样的,所以这部分逻辑可以抽取出来放到父类Sync中。
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;
}
}