多线程之 ReentrantLock 的公平锁与非公平锁

ReentrantLock 重入锁的意思。重入的意思是任意线程再获取到锁后能够再次获取该锁而不会被锁阻塞。ReentrantLock 包含公平锁和非公平锁。


ReetrantLock 的构造函数中根据boolean值的不同  FairSync 公平同步器与非公平同步器



上图中的公平同步器中获取锁时有个 hasQueuedPredecessors() 方法,这是唯一 一处与非公平同步器的地方,判断当前当前的节点是不是在同步队列的头结点上。

public class TestReentrantLock {
	
	private static ReentrantLock_copy fairLock = new ReentrantLock_copy(true);
	
	private static ReentrantLock_copy unfairLock = new ReentrantLock_copy(false);
	
	private static class ReentrantLock_copy extends ReentrantLock{
		
		public ReentrantLock_copy(boolean fair){
			super(fair);
		}
		
		public Collection<Thread> getQueuedThreads() {
			List<Thread> list = new ArrayList<>(super.getQueuedThreads());
			Collections.reverse(list);
			return list;
		}
	}
	
	private static class MyThread extends Thread{
		private ReentrantLock_copy lock;
		
		public MyThread(ReentrantLock_copy lock){
			this.lock = lock;
		}
		
		@Override
		public void run() {
			for(int i = 0;i<2;i++){
				lock.lock();
				try {
					System.out.println(Thread.currentThread().getName()+" get the lock and "+lock.getQueuedThreads().stream().map(t -> t.getName()).collect(Collectors.toList())+" are waiting...");
				} finally {
					lock.unlock();
				}
			}
			
		}
	}

	private static void testLock(ReentrantLock_copy lock) {
		MyThread my = new MyThread(lock);
		new Thread(my,"A0").start();
		new Thread(my,"A1").start();
		new Thread(my,"A2").start();
		new Thread(my,"A3").start();
		new Thread(my,"A4").start();
		new Thread(my,"A5").start();
	}
	
	public static void main(String[] args) {
		testLock(unfairLock);
		//testLock(fairLock);
	}
}

执行 testLock(unfairLock) 时  控制台输出


说明线程存在快速获得刚释放的锁,存在一个线程连续获得锁的情况


若切换为 公平锁 即执行testLock(fairLock) 控制台输出如下


以上看出线程没有连续获得锁,而是 按照 waiting中的等待顺序,获得锁。

猜你喜欢

转载自blog.csdn.net/zclworld/article/details/79826342