1. 程式人生 > >多執行緒之 ReentrantLock 的公平鎖與非公平鎖

多執行緒之 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中的等待順序,獲得鎖。