ReentrantLock 是可重入的独占锁 , 同 时 只能有 一个线程可 以 获取该锁,其他获取该锁
的线程会被阻塞而被放入该锁的 AQS 阻塞队列里面
ReentrantLock 最终还是使用 AQS 来实现的,并且根据参数来决定
其 内 部是一个公平还是非公平锁,默认是非公平锁
public ReentrantLock() {
sync = new NonfairSync();
}
/**
* Creates an instance of {@code ReentrantLock} with the
* given fairness policy.
*
* @param fair {@code true} if this lock should use a fair ordering policy
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
默认是非公平锁
其中 Sync 类直接继承自 AQS , 它的子类 NonfairSync 和 FairSync 分别实现了获取锁
的非公平与公平策略
AQS 的 state 状态值表示线程获取该锁的可重入次数 , 在默认情况下, state
的值为 0 表示当前锁没有被任何线程持有 。 当一个线程第一次获取该锁时会尝试使用 CAS
设置 state 的值为 l ,如果 CAS 成功则当前线程获取了该锁,然后记录该锁的持有者为当
前线程 。 在该线程没有释放锁的情况下第二次获取该锁后 ,状态值被设置为 2 , 这就是可
重入次数 。 在该线程释放该锁时,会尝试使用 CAS 让状态值减 1 , 如果减 l 后状态值为 o,
则 当前线程释放该锁 。
public void lock() {
sync.lock();
}
当一个线程调用该方法时 ,说明该线程希望获取该锁 。 如果锁当前没有被其他线程占
用并且当前线程之前没有获取过该锁,则当前线程会获取到该锁,然后设置当前锁的拥有
者为当前线程 , 并设置 AQS 的状态值为 1,然后直接返回 。 如果当前线程之前己经获取
过该锁,则这次只是简单地把 AQS 的状态值加 1后返回。如果该锁己经被其他线程持有,
则调用 该方法的线程会被放入 AQS 队列后阻塞挂起
ReentrantLock 的 lock()委托给了 sync 类,根据创建 ReentrantLock 构
造函数选择 sync 的实现是 NonfairSync 还是 FairSync,这个锁是一个非公平锁或者公平锁 。
这里看 sync 的子类 NonfairSync 的情况
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() {
//1) CAS设置状态值1
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
//2) 调用 AQS 的 acquire方法
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
AQS 并没有提供可用的 tryAcquire 方法 , tryAcquire 方法需要子类自己定
制化,所以这里代码( 3 )会调用 ReentrantLock 重写 的 可Acquire 方法
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
final boolean nonfairTryAcquire(int acquires) {
//获取当前线程
final Thread current = Thread.currentThread();
//获取state的值
int c = getState();
//如果是0
if (c == 0) {
//设置为1
if (compareAndSetState(0, acquires)) {
//设置独占的线程为当前线程
setExclusiveOwnerThread(current);
//返回成功
return true;
}
}
//c!=0,并且,当前线程就是获取到锁的线程
else if (current == getExclusiveOwnerThread()) {
//state的值加1 acquires=1
int nextc = c + acquires;
//如果next的值小0 可重入次数溢出了
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
//设置state的值
setState(nextc);
//返回重入锁成功
return true;
}
//如果当前线程不是锁的持有者则返回 false,然后其会被放入 AQS 阻塞队列。
return false;
}
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();
//获取state状态
int c = getState();
//判断是0
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;
}
}
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
如果当前线程节点有前驱节点则返回true, 否则如果当前 AQS 队列为空或者当前线程节点是 AQS 的第一个节点则返回 false。
其中如果 h==t 则说明当前队列为空 ,直接返回 false ;如果 h!=t 并且 s==null 则说明有一个元素将要作为 AQS 的第一个节点入队列
( enq 函数的第一个元素入队列是两步操作: 首先创建一个哨兵头节点,然后将第一个元素插入哨兵节点后面 〉,
那么返回 true,如果 h!=t 并且 s!=null和 s.thr巳ad != Thread.cunentThread()
则说明队列里面的第一个元素不是当前线程,那么返回 true 。
public void unlock() {
sync.release(1);
}
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
/**
* Performs {@link Lock#lock}. The main reason for subclassing
* is to allow fast path for nonfair version.
*/
abstract void lock();
/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
*/
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) {
//获取当前state并减1
int c = getState() - releases;
//判断获取锁的线程是不是当前线程
if (Thread.currentThread() != getExclusiveOwnerThread())
//不是就抛出异常
throw new IllegalMonitorStateException();
boolean free = false;
//如果减去 1后当前状态值为 0,则 当前线程会释放该锁
if (c == 0) {
//设置标志为true成功
free = true;
//设置获取锁的线程为null
setExclusiveOwnerThread(null);
}
//设置state的值
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();
}
final ConditionObject newCondition() {
return new ConditionObject();
}
// 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;
}
/**
* Reconstitutes the instance from a stream (that is, deserializes it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}