上一篇文章介紹了AQS的基本原理,它其實就是一個併發包的基礎組件,用來實現各類鎖,各類同步組件的。它包含了state變量、加鎖線程、等待隊列等併發中的核心組件,如今咱們來看一下多線程獲取鎖的順序問題。多線程
1 /** 2 * Creates an instance of {@code ReentrantLock}. 3 * This is equivalent to using {@code ReentrantLock(false)}. 4 */ 5 public ReentrantLock() { 6 sync = new NonfairSync(); 7 } 8 9 /** 10 * Creates an instance of {@code ReentrantLock} with the 11 * given fairness policy. 12 * 13 * @param fair {@code true} if this lock should use a fair ordering policy 14 */ 15 public ReentrantLock(boolean fair) { 16 sync = fair ? new FairSync() : new NonfairSync(); 17 }
ReentrantLock有兩個構造參數,一個有參,一個無參,默認的無參至關於有參數的false。
1 /** 2 * Performs non-fair tryLock. tryAcquire is implemented in 3 * subclasses, but both need nonfair try for trylock method. 4 */ 5 final boolean nonfairTryAcquire(int acquires) { 6 final Thread current = Thread.currentThread(); 7 int c = getState(); 8 if (c == 0) { 9 if (compareAndSetState(0, acquires)) { 10 setExclusiveOwnerThread(current); 11 return true; 12 } 13 } 14 else if (current == getExclusiveOwnerThread()) { 15 int nextc = c + acquires; 16 if (nextc < 0) // overflow 17 throw new Error("Maximum lock count exceeded"); 18 setState(nextc); 19 return true; 20 } 21 return false; 22 }
若是爲參數爲false爲非公平鎖,非公平鎖獲取鎖的方式爲若是當前沒有線程佔有鎖,當前線程直接經過cas指令佔有鎖,管他等待隊列,就算本身排在隊尾也是這樣併發
1 /** 2 * Fair version of tryAcquire. Don't grant access unless 3 * recursive call or no waiters or is first. 4 */ 5 protected final boolean tryAcquire(int acquires) { 6 final Thread current = Thread.currentThread(); 7 int c = getState(); 8 if (c == 0) { 9 if (!hasQueuedPredecessors() && 10 compareAndSetState(0, acquires)) { 11 setExclusiveOwnerThread(current); 12 return true; 13 } 14 } 15 else if (current == getExclusiveOwnerThread()) { 16 int nextc = c + acquires; 17 if (nextc < 0) 18 throw new Error("Maximum lock count exceeded"); 19 setState(nextc); 20 return true; 21 } 22 return false; 23 }
1 public final boolean hasQueuedPredecessors() { 2 // The correctness of this depends on head being initialized 3 // before tail and on head.next being accurate if the current 4 // thread is first in queue. 5 Node t = tail; // Read fields in reverse initialization order 6 Node h = head; 7 Node s; 8 return h != t && 9 ((s = h.next) == null || s.thread != Thread.currentThread()); 10 }
若是爲參數爲true爲公平鎖,公平鎖獲取鎖的方式爲若是當前線程是等待隊列的第一個或者等待隊列爲空或爲當前佔有線程,則經過cas指令設置state爲1或增長。公平鎖加鎖的線程所有是按照先來後到的順序,依次進入等待隊列中排隊的,不會盲目的胡亂搶佔加鎖。less