ReentrantLock


ReentrantLock介绍

ReentrantLock是基于Lock实现的可重入锁,所有Lock都死基于AQS实现,AQS和Condition各自维护不同的对象,在使用Lock和Condition时,其实就是两个队列的互相移动。它所提供的共享锁、互斥锁都是基于对state的操作。而它的可重入以为实现了同步器Sync,再Sync的两个实现类中,包括了公平锁和非公平锁。

源码

初始化

ReentrantLock lock = new ReentrantLock(true); // true:公平锁 lock.lock();
try {
// todo
} finally {
lock.unlock(); }
}
  • 初始化构造函数入参,选择是否为初始化公平锁。
  • 其实一般情况下并不需要公平锁,除非你的场景中需要保证顺序性。
  • 使用 ReentrantLock 切记需要在 finally 中关闭,lock.unlock()。

公平锁、非公平锁、默认

public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}

默认是非公平锁

  • 构造函数中选择公平锁(FairSync)、非公平锁(NonfairSync)。

公平锁与非公平锁的区别

hasQueuedPredecessors方法

static final class FairSync extends Sync {
	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;
				} 
	}

公平锁和非公平锁,主要是在方法 tryAcquire 中,是否 有 !hasQueuedPredecessors() 判断。

hasQueuedPredecessors

public final boolean hasQueuedPredecessors() {
	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());
}
  • 在这个判断中主要就是看当前线程是不是同步队列的首位,是:true、否:false
  • 这部分就涉及到了公平锁的实现,CLH(Craig,Landin andHagersten)。三个作者 的首字母组合

公平锁

公平锁就像是马路边上的卫生间,上厕所需要排队。当然如果有人不排队,那么 就是非公平锁了,比如领导要先上。

CLH

是一种基于单向链表的高性能、公平的自旋锁。AQS中的队列是CLH变体的虚拟双向队列(FIFO),AQS是通过将每条请求共享资源的线程封装成一个节点来实现锁的分配。

总结

  • ReentrantLock 使用起来更加灵活,可操作性也更大,但一定要在 finally 中释放 锁,目的是保证在获取锁之后,最终能够被释放。同时不要将获取锁的过程写在 try 里面。
  • 公平锁的实现依据不同场景和 SMP、NUMA 的使用,会有不同的优劣效果。在实 际的使用中一般默认会选择非公平锁,即使是自旋也是耗费性能的,一般会用在较少等待的线程中,避免自旋时过长。



Enjoy Reading This Article?

Here are some more articles you might like to read next:

  • 2379. Minimum Recolors to Get K Consecutive Black Blocks
  • 2471. Minimum Number of Operations to Sort a Binary Tree by Level
  • 1387. Sort Integers by The Power Value
  • 2090. K Radius Subarray Averages
  • 2545. Sort the Students by Their Kth Score