摘要:作者畢來生微信鎖狀態(tài)轉換分類以后幫助我們提供了線程同步機制,通過顯示定義同步鎖來實現(xiàn)對象之間的同步。等待重新嘗試因為在中是用關鍵字聲明的,故可以在線程間可見再次判斷一下能否持有鎖可能線程同步代碼執(zhí)行得比較快,已經(jīng)釋放了鎖,不可以就返回。
作者 : 畢來生鎖狀態(tài)轉換 Lock分類
微信: 878799579
? Jdk1.5以后幫助我們提供了線程同步機制,通過顯示定義同步鎖來實現(xiàn)對象之間的同步。還是Doug Lea這個家伙寫的。相信讀過源碼的人在很多地方都可以看到這個家伙。
? Lock可以顯示的進行加鎖,解鎖。但是每次只能有一個線程對Lock對象加鎖
? Lock實現(xiàn)結構如下圖所示:
? 按照使用的常用度,分別標注了(1),(2),(3)。接下來我們就主要學習一下ReentrantLock的使用
可重入鎖? ReentrantLock實現(xiàn)的前提就是AbstractQueuedSynchronizer,簡稱AQS.。核心方法內部實現(xiàn)均在AQS中,后續(xù)我們在詳細解讀AQS相關知識點以及使用場景。我們先來看一段偽代碼用以表述可重入鎖的使用情況。接下來我們來詳細分析獲取鎖以及釋放鎖內部實現(xiàn)到底做了什么事情。
package org.bilaisheng.juc; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @Author: bilaisheng * @Wechat: 878799579 * @Date: 2019/1/3 22:55 * @Todo: 偽代碼僅演示使用 * @Version : JDK11 , IDEA2018 */ public class ReentrantLockTest { public static void main(String[] args) { Lock lock = new ReentrantLock(); // 獲取鎖 lock.lock(); // access the resource protected by this lock // do something // 釋放鎖 lock.unlock(); } }Sync對象剖析
/** Synchronizer providing all implementation mechanics */ private final Sync sync; /** * Base of synchronization control for this lock. Subclassed * into fair and nonfair versions below. Uses AQS state to * represent the number of holds on the lock. */ abstract static class Sync extends AbstractQueuedSynchronizer { // xxxx }
他會根據(jù)傳入構造方法的布爾類型參數(shù)實例化出Sync的實現(xiàn)類FairSync和NoFairSync。
FairSync: 公平的Sync
NoFairSync : 不公平的Sync
public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }ReentrantLock.lock()實現(xiàn)原理
? 我們用的比較多的ReentrantLock是非公平鎖,我們來用一張圖來分析一下看看它是如何實現(xiàn)的。
上圖就做了兩件事情:
1、設置AbstractQueuedSynchronizer的state為1
2、設置AbstractOwnableSynchronizer的thread為當前線程
線程A正在執(zhí)行中,status = 1。
線程B嘗試利用CAS去判斷state是不是0,是0就設置為1,當然這一步操作肯定是失敗的,因為線程A已經(jīng)將state設置成了1,所以此時肯定是失敗的。
失敗了之后進入FIFO等待隊列。等待重新嘗試
/** * Performs non-fair tryLock. tryAcquire is implemented in * subclasses, but both need nonfair try for trylock method. */ @ReservedStackAccess final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; }
因為在AbstractQueuedSynchronizer中state是用volatile關鍵字聲明的,故可以在線程間可見
/** * The synchronization state. */ private volatile int state;
再次判斷一下能否持有鎖(可能線程A同步代碼執(zhí)行得比較快,已經(jīng)釋放了鎖),不可以就返回false。
根據(jù)上方代碼可以看出同一個鎖最多能重入Integer.MAX_VALUE次,也就是2147483647。
ReentrantLock.unLock()實現(xiàn)原理此處較為簡單。附上調用關系鏈路
// 步驟一 public void unlock() { sync.release(1); } // 步驟二 : AbstractQueuedSynchronizer public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; } //步驟二 : ReentrantLock @ReservedStackAccess protected final boolean tryRelease(int releases) { int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; }
當一條線程對同一個ReentrantLock全部解鎖之后,AQS的state就是0了,AbstractOwnableSynchronizer的exclusiveOwnerThread將被設置為null,這樣就表示沒有線程占有鎖,方法返回true。
喜歡就關注我吧文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/75675.html
摘要:如何在線程池中提交線程內存模型相關問題什么是的內存模型,中各個線程是怎么彼此看到對方的變量的請談談有什么特點,為什么它能保證變量對所有線程的可見性既然能夠保證線程間的變量可見性,是不是就意味著基于變量的運算就是并發(fā)安全的請對比下對比的異同。 并發(fā)編程高級面試面試題 showImg(https://upload-images.jianshu.io/upload_images/133416...
摘要:基礎問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關鍵字修飾符知識點總結必看篇中的關鍵字解析回調機制解讀抽象類與三大特征時間和時間戳的相互轉換為什么要使用內部類對象鎖和類鎖的區(qū)別,,優(yōu)缺點及比較提高篇八詳解內部類單例模式和 Java基礎問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...
摘要:基礎問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關鍵字修飾符知識點總結必看篇中的關鍵字解析回調機制解讀抽象類與三大特征時間和時間戳的相互轉換為什么要使用內部類對象鎖和類鎖的區(qū)別,,優(yōu)缺點及比較提高篇八詳解內部類單例模式和 Java基礎問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...
摘要:基礎問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關鍵字修飾符知識點總結必看篇中的關鍵字解析回調機制解讀抽象類與三大特征時間和時間戳的相互轉換為什么要使用內部類對象鎖和類鎖的區(qū)別,,優(yōu)缺點及比較提高篇八詳解內部類單例模式和 Java基礎問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...
閱讀 1317·2021-10-27 14:14
閱讀 3573·2021-09-29 09:34
閱讀 2477·2019-08-30 15:44
閱讀 1715·2019-08-29 17:13
閱讀 2569·2019-08-29 13:07
閱讀 866·2019-08-26 18:26
閱讀 3342·2019-08-26 13:44
閱讀 3210·2019-08-26 13:37