ReentrantLock分析

原创
2017/03/18 21:57
阅读数 106
/*非公平锁 NonfairSync*/

/*锁的获取*/
public void unlock() {
	sync.lock();
}

/**
 * <p>
	如果获取锁成功, 把同步器中的exclusiveOwnerThread设置为当前线程,获取锁失败的线程,则acquire方法,再次尝试获取锁
   </p>
 * acquire on failure.
 */
final void lock() {
	if (compareAndSetState(0, 1)) // 如果获取锁成功, 把同步器中的exclusiveOwnerThread设置为线程A
		setExclusiveOwnerThread(Thread.currentThread());
	else
		acquire(1); // 获取锁失败的线程,则执行acquire方法,再次尝试获取锁
}

/**
*  CAS  compareAndSwapInt方法参数:修改的对象、内存偏移量、修改后的期望值、待修改的值
*/
protected final boolean compareAndSetState(int expect, int update) {
	// See below for intrinsics setup to support this
	return unsafe.compareAndSwapInt(this, stateOffset, expect, update); // 
}

/**
*  同步器中的exclusiveOwnerThread设置为线程A
*/
protected final void setExclusiveOwnerThread(Thread thread) {
	exclusiveOwnerThread = thread;
}

/**
*  该方法定义在AbstractQueuedSynchronizer队列同步器中,子类可直接使用。
*  子类重写tryAcquire方法,tryAcquire调用的是nonfairTryAcquire方法。
*   如果锁未获取成功,创建一个waiter(当前线程)后放到队列中。Node.EXCLUSIVE表示独占锁
*/
// AbstractQueuedSynchronizer
public final void acquire(int arg) {
	if (!tryAcquire(arg) &&
	acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
	selfInterrupt();
}

final boolean nonfairTryAcquire(int acquires) {
	final Thread current = Thread.currentThread();
	int c = getState();
	if (c == 0) { // 如果当前state值为0,表示锁已释放,则线程可竞争锁
		if (compareAndSetState(0, acquires)) { // 如果竞争锁成功,则将同步器中的exclusiveOwnerThread设置为当前线程
			setExclusiveOwnerThread(current);
			return true;
		}
	}
	//如果不为0,意味着,锁已经被拿走了,但是,因为ReentrantLock是重入锁,是可以重复lock,unlock的,只要成对出现行。
	// 这里还要再判断一次 获取锁的线程是不是当前请求锁的线程
	else if (current == getExclusiveOwnerThread()) { 
		int nextc = c + acquires; // 如果是的,累加在state字段上就可以了
		if (nextc < 0) // overflow
			throw new Error("Maximum lock count exceeded");
		setState(nextc);
		return true;
	}
	return false;
}
/**
* 将线程放入等待队列中. 用当前线程去构造一个Node对象
*  
*/
private Node addWaiter(Node mode) {
	Node node = new Node(Thread.currentThread(), mode);
	// Try the fast path of enq; backup to full enq on failure
	Node pred = tail;
	if (pred != null) {
		node.prev = pred;
		if (compareAndSetTail(pred, node)) { // 通过CAS修改尾节点为最新的节点,并返回下一个节点
			pred.next = node;
			return node;
		}
	}
	enq(node); // 如果修改失败,意味着有并发,这个时候才会进入enq中死循环,“自旋”方式修改,直至修改成功
	return node;
}

/**
* 该方法主要的作用是将当前线程挂起
*/
final boolean acquireQueued(final Node node, int arg) {
	boolean failed = true;
	try {
		boolean interrupted = false;
		for (;;) {
			final Node p = node.predecessor();
			// 如果当前的节点是head说明他是队列中第一个“有效的”节点,因此尝试获取锁
			if (p == head && tryAcquire(arg)) {
				setHead(node); // 获取锁成功后,则将下一个节点设为头节点
				p.next = null; // help GC
				failed = false;
				return interrupted;
			}
			// 否则,检查前一个节点的状态为,看当前获取锁失败的线程是否需要挂起
			// 如果需要,借助JUC包下的LockSopport类的静态方法Park挂起当前线程。直到被唤醒
			if (shouldParkAfterFailedAcquire(p, node) &&
				parkAndCheckInterrupt())
				interrupted = true;
		}
	} finally {
		if (failed) // 如果有异常
			cancelAcquire(node); // 取消请求,对应到队列操作,就是将当前节点从队列中移除
	}
}


/*锁的释放,调用了AQS的release方法*/
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) {
	int c = getState() - releases;
	// 如果释放的线程和获取锁的线程不是同一个,抛出非法监视器状态异常
	if (Thread.currentThread() != getExclusiveOwnerThread()) 
		throw new IllegalMonitorStateException();
	boolean free = false;
	if (c == 0) {//因为是重入的关系,不是每次释放锁c都等于0,直到最后一次释放锁时,才通知AQS不需要再记录哪个线程正在获取锁。
		free = true;
		setExclusiveOwnerThread(null);
	}
	setState(c);
	return free;
}

/**
* 找到头节点,并通过LockSupport unpark方法唤醒线程
*/
private void unparkSuccessor(Node node) {
	/*
	 * If status is negative (i.e., possibly needing signal) try
	 * to clear in anticipation of signalling.  It is OK if this
	 * fails or if status is changed by waiting thread.
	 */
	int ws = node.waitStatus;
	if (ws < 0)
		compareAndSetWaitStatus(node, ws, 0);

	/*
	 * Thread to unpark is held in successor, which is normally
	 * just the next node.  But if cancelled or apparently null,
	 * traverse backwards from tail to find the actual
	 * non-cancelled successor.
	 */
	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);
}



/*公平锁*/
/**
保证公平整体性能比较低,原因是会让活跃的线程得不到锁,进入等待状态,引起线程的上下文切换
  PS:即使fair参数为true,tryLock()方法也是不保证公平的
 * Fair version of tryAcquire.  Don't grant access unless
 * recursive call or no waiters or is first.
 */
protected final boolean tryAcquire(int acquires) {
	final Thread current = Thread.currentThread();
	int c = getState();
	if (c == 0) {
		if (!hasQueuedPredecessors() &&
			compareAndSetState(0, acquires)) {
			setExclusiveOwnerThread(current);
			return true;
		}
	}
	else if (current == getExclusiveOwnerThread()) {
		int nextc = c + acquires;
		if (nextc < 0)
			throw new Error("Maximum lock count exceeded");
		setState(nextc);
		return true;
	}
	return false;
}
/**
* 查询是否有任何线程已经等待时间比当前线程更长
*/
public final boolean hasQueuedPredecessors() {
	// The correctness of this depends on head being initialized
	// before tail and on head.next being accurate if the current
	// thread is first in queue.
	Node t = tail; // Read fields in reverse initialization order
	Node h = head;
	Node s;
	return h != t &&
		((s = h.next) == null || s.thread != Thread.currentThread());
}

 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部