ReentrantLock加锁流程之tryLock方法
无参tryLock()方法
流程概述:
- 获取state值,判断是否为0
- 如果为0,竞争锁资源
- 如果不为0,判断持有锁资源的线程是否是当前线程
- 如果是,锁重入,如果不是,返回false
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
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;
}
执行逻辑:无论公平锁还是非公平锁,调用无参tryLock方法后,都会尝试获取锁资源,如果成功则返回true,如果失败,则返回false。线程不会放入队列中挂起。
有参tryLock()方法
流程概述:
- 判断当前线程是否中断,如果是,抛出中断异常
- 如果不是,竞争锁资源
- 如果竞争失败,判断时间参数是否<=0,如果是,返回false
- 如果不是,先将线程放到AQS链表中,然后判断当前线程前一个节点是否是head
- 如果是,竞争锁资源,如果不是,判断剩余时间是否<=0,如果是,返回false
- 如果不是,判断并修改前一个节点的waitStatus值
- 然后判断剩余时间是否>1000ns,如果是,挂起线程,如果不是,返回false
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
// 将时间转成纳秒级别
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
public final boolean tryAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
// 如果线程中断标志位是true,抛出中断异常
if (Thread.interrupted())
throw new InterruptedException();
// tryAcquire方法是尝试获取锁,获取成功返回true
return tryAcquire(arg) ||
doAcquireNanos(arg, nanosTimeout);
}
private boolean doAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
// 如果传入的时间<=0,直接返回false
if (nanosTimeout <= 0L)
return false;
// 计算出结束时间
final long deadline = System.nanoTime() + nanosTimeout;
// 将线程加入等待队列中
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
// 如果当前线程是head节点后面的线程,尝试获取锁资源
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return true;
}
// 获取锁资源失败,计算出剩余抢锁的时间
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0L)
// 如果时间<=0,直接返回false
return false;
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
// 线程挂起成功,并且剩余时间大于1000纳秒
// 则设置该线程挂起时间为最后一段的等待时间
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
// 线程是因为中断被唤醒
throw new InterruptedException();
}
} finally {
// 线程因为中断被唤醒,failed值还是true,所以会执行cancelAcquire方法
if (failed)
cancelAcquire(node);
}
}