前一部分详细分析了AQS的源码,这一章节来梳理分析ReenTrantLock源码(可重入独占锁,可重入互斥锁)
public class ReentrantLock implements Lock, java.io.Serializable {}
ReentrantLock实现Lock接口,以及Serializable可序列化接口。
可重入独占锁的意思是:
1、同一时间只能有一个线程持有这个锁
2、持有这个锁的线程再一次进入到另一个被这个锁锁住的模块,即这个锁的线程可以重复获取锁
一. Lock接口
package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;
public interface Lock {
// 获取锁,如果获取不到就一直等,不响应中断请求
void lock();
// 获取锁,如果获取不到就一直等,如果在线程等待期间有中断请求则抛出异常
void lockInterruptibly() throws InterruptedException;
// 尝试用非公平锁的方式去获取锁,立即返回。返回TRUE表示成功,返回FALSE表示失败
boolean tryLock();
// 在规定的unit单位时间为获取锁,如果时间到了还没获取到所,则返回FALSE表示失败
// 如果在线程等待期间有中断请求则抛出异常
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
// 当前线程释放占用的锁,并唤醒这个锁上的一个等待线程
void unlock();
// 创建一个Condition对象
Condition newCondition();
}
这个接口提供获取锁,释放锁以及生成Condition对象的方法。
二. 构造函数和成员属性
2.1 成员属性
// ReentrantLock通过Sync变量,实现独占锁的操作
// Sync是AQS的子类
private final Sync sync;
ReentrantLock只有这一个成员变量,它是AQS的子类,所以可以通过sync实现独占锁的操作。
2.2 构造函数
// 默认构造函数,实现非公平锁
public ReentrantLock() {
sync = new NonfairSync();
}
// 根据fair值,来获取锁,TRUE为公平锁,FLASE非公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
根据参数fair来决定是公平锁还是非公平锁,默认是非公平锁。
三. Sync内部类
这个类也是个抽象类,它的两个子类就是FairSync和NonfairSync。有两个重要方法。
3.1 nonfairTryAcquire方法
使用非公平方式去尝试获取锁
// 非公平锁方式获取
final boolean nonfairTryAcquire(int acquires) {
// 记录当前线程
final Thread current = Thread.currentThread();
// 获取锁的记录状态
int c = getState();
// c == 0表示空闲
if (c == 0) {
// 直接CAS模式更改锁的记录状态
if (compareAndSetState(0, acquires)) {
// 设置当前线程为独占锁的线程
setExclusiveOwnerThread(current);
return true;
}
}
// 判断当前线程是否为独占锁
else if (current == getExclusiveOwnerThread()) {
// state状态累加(相当于加一操作)
int nextc = c + acquires;
// 溢出
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
// 更改锁记录状态,因为一个线程独占不用CAS
setState(nextc);
return true;
}
return false;
}
方法流程:
- 调用getState方法获取锁的记录状态c
- 如果c==0表示当前锁是空闲的。因为是非公平的方法获取锁,所以直接调用compareAndSetState更改锁的状态,如果成功,表示当前线程获取了锁,如果失败,表示锁的状态别的线程更改了,当前线程获取锁失败。
- 如果c不等于0,那么要看当前线程是不是获取锁的线程,因为ReentrantLock是可重入锁,获取锁的线程可以重复获取锁。
3.2 tryRelease方法
尝试释放锁资源,返回true表示完全释放了锁资源,返回false表示还持有锁资源。
因为锁是可重入的,所以锁可能要释放多次。
protected final boolean tryRelease(int releases) {
// 新的状态值(state减一操作)
int c = getState() - releases;
// 判断当前状态是否为独占锁,不是的话抛出异常
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
// 标记是否可以释放锁
boolean free = false;
// 如果新的状态为空闲状态,表示可以释放锁
if (c == 0) {
free = true;
// 设置当前独占锁的线程为NULL
setExclusiveOwnerThread(null);
}
// 更改新的状态值
setState(c);
return free;
}
- 先计算新的锁的记录状态c。
- 如果当前线程不是独占锁的线程,就抛出IllegalMonitorStateException异常。
- 当新的锁的记录状态为0时,表示完全释放锁资源,就唤醒另一个等待锁的线程了。
- 设置新的锁的记录状态。
四. NonfairSync 非公平锁
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
// 获取锁,如果没有获取到锁,当前线程需要阻塞等待
final void lock() {
// 设置属性,期望值0(空闲),更新值1,如果设置成功,返回TRUE
if (compareAndSetState(0, 1))
// 设置当前线程为独占锁
setExclusiveOwnerThread(Thread.currentThread());
else
// 调用acquire方法,获取锁
acquire(1);
}
// 尝试获取锁,获取到锁返回true,没有获取到返回false
protected final boolean tryAcquire(int acquires) {
// 调用父类nonfairTryAcquire
return nonfairTryAcquire(acquires);
}
}
继承Sync类需要复写两个方法:
- lock获取锁的方法。 因为是非公平锁方式获取锁,所以先直接调用compareAndSetState方法,如果返回true,表示锁资源被当前线程持有了。返回false表示锁的状态state不是0,锁资源已经被持有了。则调用acquire方法,再次获取锁,不成功就阻塞当前线程。
- tryAcquire方法:尝试获取锁,获取到锁返回true,没有获取到返回false。这里调用父类的nonfairTryAcquire方法
五. FairSync 公平锁
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
// 与非公平锁不同,他需要考虑线程等待队列里面是否有值
acquire(1);
}
// 尝试获取锁,与非公平锁最大的不同就是,调用了hasQueuedPredecessors判断当前节点是否是等待队列的头节点
// hasQueuedPredecessors方法返回true,表示等待线程队列中有一个线程在当前线程之前,
// 根据公平锁的规则,当前线程不能获取锁。
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;
}
}
lock 方法:与非公平锁相比,它直接调用acquire方法,因为是公平锁,所以必须考虑当前线程是不是CLH队列中第一个(即队列中第一个等待线程)
tryAcquire 方法:与非公平锁相比,会调用调用hasQueuedPredecessors()方法。 hasQueuedPredecessors方法返回true,表示等待线程队列中有一个线程在当前线程之前,根据公平锁的规则,当前线程不能获取锁。
附录
package java.util.concurrent.locks;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
public class ReentrantLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = 7373984872572414699L;
// ReentrantLock通过sync属性,实现独占锁的操作。
// Sync是AbstractQueuedSynchronizer的子类
private final Sync sync;
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();
// 获取锁的记录状态state
int c = getState();
// 如果c==0表示当前锁是空闲的
if (c == 0) {
// 通过CAS原子操作方式设置锁的状态,如果为true,表示当前线程获取的锁,
// 为false,锁的状态被其他线程更改,当前线程获取的锁失败
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) {
// c表示新的锁的记录状态
int c = getState() - releases;
// 如果当前线程不是独占锁的线程,就抛出IllegalMonitorStateException异常
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
// 标志是否可以释放锁
boolean free = false;
// 当新的锁的记录状态为0时,表示可以释放锁
if (c == 0) {
free = true;
// 设置独占锁的线程为null
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() {
// 只有当前线程是独占锁的线程,才会返回锁的记录状态state,否则返回0
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
}
}
/**
* 非公平锁
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
// 获取锁,如果没有获取到锁,则当前线程要阻塞等待
final void lock() {
// compareAndSetState返回true,表示当前线程获取锁成功。
// 因为是非公平锁,所以不需要判断AbstractQueuedSynchronizer线程等待队列是否有值
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
// 调用acquire方法,获取锁
acquire(1);
}
// 尝试获取锁,获取到锁返回true,没有获取到返回false
protected final boolean tryAcquire(int acquires) {
// 调用父类的nonfairTryAcquire方法
return nonfairTryAcquire(acquires);
}
}
/**
* 公平锁
*/
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
// 与非公平锁不同,因为它要考虑线程等待队列是否有值
acquire(1);
}
// 尝试获取锁,与与非公平锁最大的不同就是调用hasQueuedPredecessors()方法
// hasQueuedPredecessors方法返回true,表示等待线程队列中有一个线程在当前线程之前,
// 根据公平锁的规则,当前线程不能获取锁。
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
// 获取锁的记录状态
int c = getState();
// 如果c==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 ReentrantLock() {
sync = new NonfairSync();
}
// 根据fair值,决定创建公平锁还是非公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
// 获取锁,如果获取不到,就一直等待。不响应中断请求
public void lock() {
sync.lock();
}
// 获取锁,如果获取不到,就一直等待。如果有中断请求就抛出异常
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
// 尝试用非公平锁方式去获取锁,立即返回。返回true表示获取成功,返回false表示获取失败
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
// 在规定的unit时间内获取锁,如果时间到了还没有获取到锁,则返回false,表示获取失败
// 如果在线程等待期间有中断请求就抛出异常
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
// 当前线程释放占用的锁,并唤醒这个锁上的一个等待线程
public void unlock() {
sync.release(1);
}
// 创建一个Condition对象
public Condition newCondition() {
return sync.newCondition();
}
//
public int getHoldCount() {
return sync.getHoldCount();
}
// 当前线程是不是持有锁的线程
public boolean isHeldByCurrentThread() {
return sync.isHeldExclusively();
}
// 锁是否已经被持有
public boolean isLocked() {
return sync.isLocked();
}
// 是不是公平锁
public final boolean isFair() {
return sync instanceof FairSync;
}
// 返回持有锁的线程,如果null,表示没有任何线程持有锁
protected Thread getOwner() {
return sync.getOwner();
}
// 是不是有等待锁的线程,即锁的同步队列是不是不为空
public final boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
// 等待锁的线程队列中有没有thread线程
public final boolean hasQueuedThread(Thread thread) {
return sync.isQueued(thread);
}
// 等待锁线程队列的长度
public final int getQueueLength() {
return sync.getQueueLength();
}
// 返回等到锁的线程队列的集合
protected Collection<Thread> getQueuedThreads() {
return sync.getQueuedThreads();
}
// condition对象的condition队列是否有等待线程
public boolean hasWaiters(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
}
// condition对象上等待线程的个数
public int getWaitQueueLength(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
}
// condition对象上等待线程的集合
protected Collection<Thread> getWaitingThreads(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
}
public String toString() {
Thread o = sync.getOwner();
return super.toString() + ((o == null) ?
"[Unlocked]" :
"[Locked by thread " + o.getName() + "]");
}
}
对很少部分做整理,自己梳理一遍代码思路更加清晰,膜拜原作者!侵删!
本文参考:https://www.jianshu.com/p/93da503acfb8