二十二、ReentrantReadWriteLock之写锁释放流程

51 阅读1分钟

ReentrantReadWriteLock之写锁释放流程

流程概述:

  1. 判断当前线程是否持有锁,如果不持有,抛出异常
  2. 将state值-1,判断state值是否为0
  3. 如果不为0,锁释放流程结束
  4. 如果为0,判断head节点的waitStatus值是否为0
  5. 如果不为0,说明有待唤醒的节点
  6. 将head的waitStatus值设置为0,判断head的next节点是否是有效节点
  7. 如果不是,从AQS链表的最后一个节点开始往前找,寻找到离head节点最近的节点
  8. 然后唤醒此节点
public void unlock() {
	sync.release(1);
}

public final boolean release(int arg) {
	if (tryRelease(arg)) {
		Node h = head;
		if (h != null && h.waitStatus != 0)
			unparkSuccessor(h);
		return true;
	}
	return false;
}

protected final boolean tryRelease(int releases) {
	// 判断当前线程是否持有锁
	if (!isHeldExclusively())
		// 当前线程不持有锁
		throw new IllegalMonitorStateException();
	// state值-1,释放锁资源
	int nextc = getState() - releases;
	// 判断state值-1后,低16位是否为0
	boolean free = exclusiveCount(nextc) == 0;
	if (free)
		// 如果state值-1后低16位为0,设置当前持有锁资源的线程为null
		setExclusiveOwnerThread(null);
	setState(nextc);
	return free;
}

private void unparkSuccessor(Node node) {
	int ws = node.waitStatus;
	if (ws < 0)
		compareAndSetWaitStatus(node, ws, 0);

	Node s = node.next;
	if (s == null || s.waitStatus > 0) {
		s = null;
		for (Node t = tail; t != null && t != node; t = t.prev)
			if (t.waitStatus <= 0)
				s = t;
	}
	if (s != null)
		LockSupport.unpark(s.thread);
}