二十一、ReentrantReadWriteLock之写锁加锁流程

29 阅读1分钟

ReentrantReadWriteLock之写锁加锁流程

写锁的加锁流程:

  1. 获取state值的低16位值
  2. 判断是否有线程持有锁资源
  3. 如果有线程持有读锁,返回false;或者有线程持有写锁,但是不是当前线程,返回false
  4. 否则,是当前线程持有写锁,进行重入锁流程
  5. 如果没有线程持有锁,判断当前线程竞争的是公平锁还是非公平锁
  6. 如果是公平锁,加入同步队列挂起;如果是非公平锁,竞争一波锁资源
public void lock() {
	sync.acquire(1);
}

public final void acquire(int arg) {
	if (!tryAcquire(arg) &&
		acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
		selfInterrupt();
}

protected final boolean tryAcquire(int acquires) {
	// 获取当前线程
	Thread current = Thread.currentThread();
	// 获取state值
	int c = getState();
	// 获取state低16位值
	int w = exclusiveCount(c);
	// 判断是否有线程获得锁
	if (c != 0) {
		// 有线程获得锁
		// 判断是否有线程获得写锁
		// 或者获得写锁的线程是否是当前线程
		if (w == 0 || current != getExclusiveOwnerThread())
			// 获得写锁的线程不是当前线程
			return false;
		// 当前线程获得写锁
		// 判断写锁重入次数是否达到上限
		if (w + exclusiveCount(acquires) > MAX_COUNT)
			throw new Error("Maximum lock count exceeded");
		// 写锁重入次数没有达到上限
		// 追加锁重入次数
		setState(c + acquires);
		return true;
	}
	// 没有线程获得锁
	// writerShouldBlock方法判断线程是否应该挂起,非公平锁返回false
	// 公平锁判断AQS中是否有线程排队,如果有,head的next节点是否是当前线程,如果是,返回false
	// 非公平锁的情况下判断是否获得锁
	if (writerShouldBlock() ||
		!compareAndSetState(c, c + acquires))
		// 没有获得锁
		return false;
	// 获得锁
	setExclusiveOwnerThread(current);
	return true;
}