十、ReentrantLock加锁流程之tryLock方法

60 阅读2分钟

ReentrantLock加锁流程之tryLock方法

无参tryLock()方法

流程概述:

  1. 获取state值,判断是否为0
  2. 如果为0,竞争锁资源
  3. 如果不为0,判断持有锁资源的线程是否是当前线程
  4. 如果是,锁重入,如果不是,返回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()方法

流程概述:

  1. 判断当前线程是否中断,如果是,抛出中断异常
  2. 如果不是,竞争锁资源
  3. 如果竞争失败,判断时间参数是否<=0,如果是,返回false
  4. 如果不是,先将线程放到AQS链表中,然后判断当前线程前一个节点是否是head
  5. 如果是,竞争锁资源,如果不是,判断剩余时间是否<=0,如果是,返回false
  6. 如果不是,判断并修改前一个节点的waitStatus值
  7. 然后判断剩余时间是否>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);
	}
}