ReentrantLock 可重入鎖 字面意思理解為同一線程可以重入加鎖
AbstractQueuedSynchronizer 源碼解析 可以先看這篇文章瞭解AQS原理
內部主要邏輯繼承AQS來實現的,有兩種實現FairSycn、NonfairSync,公平鎖和非公平鎖,默認為非公平鎖。
- 公平鎖:保證先入隊的先獲得鎖。
- 非公平鎖:不保證先入隊的先獲得鎖,可能後面的線程先搶到鎖。
主要實現流程
state值默認為0,當state=0時,線程通過CAS爭搶鎖,獲取到鎖時state值為1,同一個線程多次獲取鎖state值+1,解鎖時-1直到為0時釋放鎖,未獲取到鎖的線程加入CLH隊列阻塞LockSupport.park()等待,鎖釋放時通過CLH隊列關聯喚醒LockSupport.unpark()等待的線程去獲取鎖
CAS全名compare and swap比較交換,由native方法提供的系統原子性操作,以保證併發發安全性。
-
公平鎖的實現
加鎖
//加鎖 final void lock() { acquire(1);//調用AQS方法 }//AQS方法 public final void acquire(int arg) { if (!tryAcquire(arg) &&//嘗試獲取鎖,抽象方法由子類實現 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) /* addWaiter 將線程加入等待隊列 * acquireQueued 嘗試獲取鎖、阻塞 */ { //中斷 selfInterrupt(); } }//嘗試獲取鎖 protected final boolean tryAcquire(int acquires) { //獲取當前線程 final Thread current = Thread.currentThread(); int c = getState();//獲取state值,AQS屬性volatile標記 if (c == 0) {//鎖空閒狀態 if (!hasQueuedPredecessors() &&//是否需要排隊 compareAndSetState(0, acquires)) {//獲取鎖 setExclusiveOwnerThread(current);//成功獲取,設置鎖owner為當前線程 return true;//後續不在處理 } } else if (current == getExclusiveOwnerThread()) {//當前線程已持有鎖,重入 int nextc = c + acquires;//state+1 if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc);//已持有鎖,直接設置state值 return true; } return false; }解鎖
//解鎖,ReentrantLock方法 public void unlock() { sync.release(1);//AQS方法 }//AQS解鎖 public final boolean release(int arg) { if (tryRelease(arg)) {//嘗試解鎖 Node h = head; if (h != null && h.waitStatus != 0)//waitStatus=0時不進行unpark(喚醒),next線程可能中斷 unparkSuccessor(h);//喚醒隊列中的線程去獲取鎖 return true; } return false; }//嘗試解鎖ReentrantLock內部靜態類Sync實現 protected final boolean tryRelease(int releases) { int c = getState() - releases;//state-1 if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException();//非持有鎖的線程進行釋放,非法操作 boolean free = false; if (c == 0) {//持有鎖線程全部釋放 free = true; setExclusiveOwnerThread(null);//持有鎖線程置空 } setState(c);//持有鎖線程直接設置state return free; } -
非公平鎖的實現
非公平鎖和公平鎖的核心區別是在嘗試獲取鎖方法tryAcquire實現中沒有判斷hasQueuedPredecessors()是否需要排隊,其他邏輯和公平鎖是一致的。