1.下面先分析一下ReentrantLock类
private final Sync sync;
ReentrantLock持有了sync变量,Sync类下面有FairSync和NonfairSync,也就是通常所说的公平锁和非公平锁。
2.构造方法
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
调用构造方法创建锁时,默认创建非公平锁,也可以传入boolean参数选择创建公平锁或非公平锁。
3.成员方法
//调用具体公平锁/非公平锁的lock方法获取锁,获取失败会进入等待队列等待
public void lock() {
sync.lock();
}
//同上也是获取锁的方法,会检查当前线程是否被中断,如果中断会抛InterruptedException异常
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
//非公平获取锁,也就是通过cas直接去争抢锁,争抢失败则返回false,只争抢一次
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
//带超时的获取锁的方法,线程会阻塞进入等待队列,如果时间超时则取消等待
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
//释放锁
public void unlock() {
sync.release(1);
}
public Condition newCondition() {
return sync.newCondition();
}
//获取重入次数,返回的是state状态的值,state表示锁每被获取一次,值+1,为0表示锁未被获取
public int getHoldCount() {
return sync.getHoldCount();
}
//锁是否被当前线程持有
public boolean isHeldByCurrentThread() {
return sync.isHeldExclusively();
}
//锁是否被占用,判断state是否=0
public boolean isLocked() {
return sync.isLocked();
}
//判断当前锁是否是公平锁
public final boolean isFair() {
return sync instanceof FairSync;
}
//获取占用锁的独占线程
protected Thread getOwner() {
return sync.getOwner();
}
//是否有线程排队等待获取锁
public final boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
//指定线程是否在等待获取锁,通过遍历等待队列链表的方式判断
public final boolean hasQueuedThread(Thread thread) {
return sync.isQueued(thread);
}
//获取等待队列长度,也是通过遍历的方式计算
public final int getQueueLength() {
return sync.getQueueLength();
}
//获取等待队列的所有线程
protected Collection<Thread> getQueuedThreads() {
return sync.getQueuedThreads();
}
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);
}
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);
}
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);
}
4.ReentrantLock.tryLock方法
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
//AQS中的方法,先是调用tryAcquire尝试获取锁,如果锁被占用获取失败则再调用doAcquireNanos
//arg参数为1,表示获取锁成功后将独占锁的状态加1
public final boolean tryAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
return tryAcquire(arg) ||
doAcquireNanos(arg, nanosTimeout);
}
//****FairSync的tryAcquire****
//从这里可以看出state的值如果大于0则说明被占用了,而这个值越大说明锁被重入的次数越多
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//1.如果锁的状态为0(锁空闲),则继续判断当前线程前面是否还有节点在排队;如果
//当前线程是第一个节点,那么CAS修改同步器状态为1(抢占锁);再设置当前线程为独占线程。
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//2.如果锁被当前线程占用,则说明是重入获取锁,将状态值进行增加。(从这里可以看出state的值等于锁被线程重入的次数)
//如果增加后的值小于0了,说明获取锁的次数超出了int的上限,抛出次数上限的error。
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
//****AQS的doAcquireNanos方法**** 超时获取不到锁则放弃获取,会判断线程中断
private boolean doAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
//如果获取时间小于等于0,那么说明已超时
if (nanosTimeout <= 0L)
return false;
//获取最后超时时间
final long deadline = System.nanoTime() + nanosTimeout;
//入队一个当前线程的独占节点到等待队列的尾部
final Node node = addWaiter(Node.EXCLUSIVE);
//用于执行下面finally块的cancelAcquire方法释放节点
boolean failed = true;
try {
for (;;) {
//获取尾部节点的前继节点
final Node p = node.predecessor();
//如果前一个节点是头结点那么就尝试获取锁
if (p == head && tryAcquire(arg)) {
//获取锁成功设置头节点为当前线程的节点
setHead(node);
//把原来的头节点的next置为空,用于GC
p.next = null; // help GC
//状态值改变,finally中不需要再释放节点
failed = false;
//返回获取锁成功
return true;
}
//用时间截止线-当前时间,判断获取时间是否超时,超时则自动返回获取锁失败
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0L)
return false;
//判断该节点的线程获取锁失败后,是否需要休息(进入waiting状态),如果是,则再判断剩余超时时间是否充足(大于spinForTimeoutThreshold),如果上述两个条件都满足则让当前线程进入waiting状态,等待唤醒
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
上面是公平锁的获取锁代码, 可以看出公平锁是每一次只能头结点的后继节点才能有资格获取锁,获取锁通过cas完成。
而非公平锁是任何节点都会使用cas去抢占获取锁,没有先后顺序之分,可能先到的后获取到锁,也可能会一直等待(这称为线程饥饿)
static final class NonfairSync extends Sync {
final void lock() {
//cas获取锁,把锁的状态从0修改成1,如果修改成功则说明抢占到锁的使用了,将锁的独占线程修改成当前线程
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
//如果抢占失败则调用acquire方法再次获取,并进入阻塞
acquire(1);
}
//调用非公平获取锁方法
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
//1.先调用tryAcquire方法尝试获取锁,这里调用的就是上面非公平锁重写的nonfairTryAcquire方法
//2.如果尝试获取锁失败,那么则添加当前线程到等待队列尾部,进入waiting状态
//3.进入中断状态
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}