
在 Java 并發(fā)編程體系中synchronized內(nèi)置鎖與ReentrantLock顯式鎖是實(shí)現(xiàn)線程同步、保證并發(fā)安全的兩大核心方案。絕大多數(shù)開發(fā)者只會(huì)表層使用synchronized 簡(jiǎn)單、ReentrantLock 靈活但完全說不清核心差異為什么 JDK1.6 優(yōu)化后 synchronized 性能反超 ReentrantLock顯式鎖靈活在哪里什么場(chǎng)景必須放棄 synchronized 用 ReentrantLock兩者的底層鎖機(jī)制、調(diào)度邏輯、并發(fā)能力有哪些本質(zhì)區(qū)別一、前置核心認(rèn)知兩大鎖的本質(zhì)定位1.1 synchronizedJVM 原生內(nèi)置隱式鎖synchronized 是 Java 語言原生關(guān)鍵字由 JVM 底層硬編碼實(shí)現(xiàn)屬于隱式鎖。鎖的獲取、釋放全部由 JVM 自動(dòng)管控開發(fā)者無需手動(dòng)干預(yù)簡(jiǎn)單無腦、自動(dòng)兜底。核心定位極簡(jiǎn)通用型同步鎖主打低學(xué)習(xí)成本、自動(dòng)安全、無需手動(dòng)運(yùn)維適配絕大多數(shù)普通并發(fā)場(chǎng)景。1.2 ReentrantLockJDK 代碼實(shí)現(xiàn)顯式鎖ReentrantLock 是java.util.concurrent.locks包下的工具類鎖基于 AQS抽象隊(duì)列同步器純代碼實(shí)現(xiàn)屬于顯式鎖。鎖的獲取、釋放、調(diào)度策略全部由開發(fā)者手動(dòng)編碼控制高度靈活。核心定位高階增強(qiáng)型同步鎖主打高靈活性、可定制、強(qiáng)并發(fā)能力適配復(fù)雜、高并發(fā)、精細(xì)化管控的業(yè)務(wù)場(chǎng)景。二、底層實(shí)現(xiàn)原理深度拆解最核心差異2.1 synchronized 底層原理JVM 層級(jí)鎖升級(jí)機(jī)制JDK1.6 之前synchronized 是笨重的重量級(jí)鎖依賴操作系統(tǒng) Mutex 互斥量需要用戶態(tài)與內(nèi)核態(tài)切換開銷極大。JDK1.6 對(duì)其進(jìn)行極致自適應(yīng)優(yōu)化引入三級(jí)鎖升級(jí)機(jī)制全程自動(dòng)適配場(chǎng)景無需開發(fā)者干預(yù)無競(jìng)爭(zhēng)場(chǎng)景偏向鎖零開銷、無CAS、無同步操作單線程重復(fù)加鎖直接放行輕微競(jìng)爭(zhēng)場(chǎng)景輕量級(jí)鎖用戶態(tài)CAS自旋無線程阻塞、無內(nèi)核切換用少量CPU空轉(zhuǎn)避免阻塞開銷激烈競(jìng)爭(zhēng)場(chǎng)景重量級(jí)鎖依托操作系統(tǒng)內(nèi)核互斥量線程阻塞入隊(duì)犧牲內(nèi)核開銷保證并發(fā)穩(wěn)定核心底層特點(diǎn)鎖狀態(tài)存儲(chǔ)在對(duì)象頭 Mark Word中鎖升級(jí)單向不可逆全程 JVM 自動(dòng)調(diào)度無人工干預(yù)空間。2.2 ReentrantLock 底層原理AQS 獨(dú)占可重入機(jī)制ReentrantLock 從 JDK1.5 誕生之初底層就固定基于AQSAbstractQueuedSynchronizer實(shí)現(xiàn)無鎖升級(jí)機(jī)制從始至終都是統(tǒng)一的獨(dú)占鎖模型。核心底層邏輯依托 AQS 的state 狀態(tài)變量記錄鎖持有次數(shù)實(shí)現(xiàn)可重入特性依托 AQS雙向阻塞隊(duì)列完成搶鎖失敗線程的排隊(duì)、喚醒、調(diào)度原生支持公平鎖/非公平鎖手動(dòng)切換默認(rèn)非公平鎖所有鎖競(jìng)爭(zhēng)、排隊(duì)、喚醒邏輯均為Java 代碼層級(jí)實(shí)現(xiàn)不依賴操作系統(tǒng)內(nèi)核核心底層特點(diǎn)無自適應(yīng)鎖升級(jí)純用戶態(tài)代碼調(diào)度靈活性拉滿、可定制性極強(qiáng)但簡(jiǎn)單場(chǎng)景下冗余邏輯更多。三、核心功能與特性全方位對(duì)比3.1 鎖的可重入性共同點(diǎn)兩者均支持可重入同一個(gè)線程獲取鎖后可重復(fù)加鎖不會(huì)出現(xiàn)自己阻塞自己的死鎖問題。synchronizedJVM 底層自動(dòng)記錄重入次數(shù)無需手動(dòng)計(jì)數(shù)自動(dòng)解鎖ReentrantLock基于 AQS state 變量計(jì)數(shù)加鎖 state1解鎖 state-1必須成對(duì)解鎖3.2 鎖釋放機(jī)制核心差異synchronized隱式釋放代碼執(zhí)行完畢、異常拋出時(shí)JVM自動(dòng)釋放鎖絕對(duì)不會(huì)出現(xiàn)鎖泄露安全性極高ReentrantLock顯式釋放必須手動(dòng)在finally 代碼塊中調(diào)用 unlock()釋放鎖代碼異常、忘記釋放會(huì)直接導(dǎo)致永久鎖泄露、線程死鎖3.3 公平鎖支持synchronized僅支持非公平鎖無任何手動(dòng)配置方式鎖釋放后隨機(jī)喚醒等待線程無法保證先來先到ReentrantLock原生雙模式支持構(gòu)造方法傳入 true 開啟公平鎖FIFO排隊(duì)默認(rèn)非公平鎖可自由切換3.4 鎖等待可控性synchronized搶鎖失敗線程永久阻塞無法超時(shí)、無法中斷極易出現(xiàn)線程卡死、服務(wù)雪崩問題ReentrantLock提供tryLock()超時(shí)搶鎖、lockInterruptibly()可中斷搶鎖完全可控從根源規(guī)避死鎖和永久阻塞3.5 精準(zhǔn)喚醒機(jī)制synchronized依托 Object 的 wait/notify只能隨機(jī)喚醒一個(gè)線程或全部喚醒無法精準(zhǔn)喚醒存在無效喚醒、資源浪費(fèi)問題ReentrantLock依托Condition 條件隊(duì)列可創(chuàng)建多個(gè)條件隊(duì)列實(shí)現(xiàn)精準(zhǔn)分組喚醒按需喚醒指定線程并發(fā)效率更高3.6 鎖狀態(tài)可監(jiān)控synchronized無任何 API 可監(jiān)控鎖狀態(tài)無法判斷是否加鎖、是否被占用、等待線程數(shù)量排查問題困難ReentrantLock提供豐富監(jiān)控 APIisLocked()、getQueueLength()、hasWaiters()可實(shí)時(shí)監(jiān)控鎖狀態(tài)、線程排隊(duì)情況便于線上問題排查四、性能差異深度解析架構(gòu)師必懂4.1 JDK1.6 前后性能反轉(zhuǎn)JDK1.5 及之前synchronized 只有重量級(jí)鎖內(nèi)核切換開銷巨大性能遠(yuǎn)差于 ReentrantLockJDK1.6 及之后synchronized 引入自適應(yīng)鎖升級(jí)無競(jìng)爭(zhēng)/輕微競(jìng)爭(zhēng)場(chǎng)景開銷極低整體性能反超 ReentrantLock4.2 不同場(chǎng)景性能表現(xiàn)低競(jìng)爭(zhēng)、單線程場(chǎng)景synchronized 偏向鎖零開銷性能優(yōu)于 ReentrantLockReentrantLock 存在 AQS 代碼邏輯冗余開銷中等交替競(jìng)爭(zhēng)場(chǎng)景兩者性能持平synchronized 輕量級(jí)鎖 CAS 自旋與 AQS 調(diào)度開銷相近高并發(fā)激烈競(jìng)爭(zhēng)場(chǎng)景ReentrantLock 性能更優(yōu)可通過公平鎖、超時(shí)機(jī)制、精準(zhǔn)喚醒減少無效競(jìng)爭(zhēng)而 synchronized 極易直接升級(jí)為重量級(jí)鎖性能暴跌五、全方位核心差異對(duì)比表對(duì)比維度Synchronized內(nèi)置鎖ReentrantLock顯式鎖實(shí)現(xiàn)層級(jí)JVM 底層原生實(shí)現(xiàn)關(guān)鍵字JDK 代碼層級(jí)實(shí)現(xiàn)AQS 工具類鎖模式僅非公平鎖不可配置公平/非公平鎖可手動(dòng)切換鎖釋放方式自動(dòng)釋放代碼結(jié)束/異常安全無泄露手動(dòng) unlock() 釋放需 finally 兜底易泄露等待可控性不可超時(shí)、不可中斷永久阻塞支持超時(shí)搶鎖、可中斷搶鎖完全可控喚醒機(jī)制notify()/notifyAll()隨機(jī)/全部喚醒無精準(zhǔn)控制Condition 精準(zhǔn)分組喚醒按需喚醒鎖監(jiān)控能力無監(jiān)控 API無法排查鎖狀態(tài)豐富監(jiān)控 API可查看排隊(duì)、等待線程數(shù)底層機(jī)制偏向鎖→輕量級(jí)鎖→重量級(jí)鎖 自適應(yīng)升級(jí)AQS 雙向隊(duì)列 state 計(jì)數(shù)無鎖升級(jí)代碼簡(jiǎn)潔度極簡(jiǎn)一行關(guān)鍵字搞定繁瑣需手動(dòng)加鎖、解鎖、異常兜底可重入性支持JVM 自動(dòng)計(jì)數(shù)兜底支持AQS state 手動(dòng)計(jì)數(shù)適用場(chǎng)景低并發(fā)、普通同步、簡(jiǎn)單場(chǎng)景高并發(fā)、復(fù)雜同步、需要精細(xì)化管控場(chǎng)景六、精準(zhǔn)選型口訣落地核心6.1 優(yōu)先選擇 Synchronized 的場(chǎng)景選型口訣簡(jiǎn)單同步、低并發(fā)、無需特殊管控一律用 synchronized普通方法、代碼塊同步邏輯簡(jiǎn)單并發(fā)競(jìng)爭(zhēng)不激烈單線程/少量線程交替執(zhí)行追求代碼簡(jiǎn)潔、低維護(hù)成本、杜絕鎖泄露不需要超時(shí)鎖、公平鎖、精準(zhǔn)喚醒等特殊能力架構(gòu)師思考JDK1.6 后 synchronized 性能足夠優(yōu)秀且自動(dòng)兜底、零運(yùn)維簡(jiǎn)單場(chǎng)景用它性價(jià)比最高。6.2 必須選擇 ReentrantLock 的場(chǎng)景選型口訣需靈活管控、高并發(fā)、防死鎖、精準(zhǔn)同步必用 ReentrantLock需要公平鎖必須保證線程先來先到杜絕線程饑餓需要超時(shí)搶鎖防止永久阻塞、規(guī)避死鎖服務(wù)容錯(cuò)優(yōu)先精準(zhǔn)線程喚醒生產(chǎn)者消費(fèi)者、多條件分組等待場(chǎng)景高并發(fā)激烈競(jìng)爭(zhēng)需要穩(wěn)定可控的鎖調(diào)度避免鎖升級(jí)重量級(jí)鎖雪崩線上鎖問題排查需要監(jiān)控鎖狀態(tài)、線程排隊(duì)數(shù)量七、生產(chǎn)環(huán)境高頻避坑指南7.1 Synchronized 避坑點(diǎn)禁止同步代碼塊過長執(zhí)行耗時(shí)過久會(huì)導(dǎo)致鎖競(jìng)爭(zhēng)激烈快速升級(jí)為重量級(jí)鎖吞吐量暴跌避免鎖對(duì)象變更鎖對(duì)象為變量時(shí)對(duì)象替換會(huì)導(dǎo)致鎖失效引發(fā)并發(fā)安全問題杜絕永久阻塞場(chǎng)景無超時(shí)、不可中斷特性高并發(fā)下易造成線程堆積、服務(wù)卡死明確鎖范圍盡量縮小同步粒度只鎖核心共享代碼避免大范圍鎖競(jìng)爭(zhēng)7.2 ReentrantLock 避坑點(diǎn)必須 finally 解鎖絕對(duì)禁止忘記 unlock()、異常跳過解鎖直接導(dǎo)致鎖泄露、死鎖tryLock 必須判空不判斷搶鎖成功狀態(tài)直接執(zhí)行業(yè)務(wù)引發(fā)線程安全問題重入鎖成對(duì)解鎖多次加鎖必須對(duì)應(yīng)多次解鎖否則鎖無法釋放不濫用公平鎖公平鎖犧牲性能換順序無業(yè)務(wù)需求默認(rèn)用非公平鎖八、全文核心總結(jié)1.本質(zhì)區(qū)別synchronized 是 JVM 自動(dòng)管控的隱式鎖主打簡(jiǎn)單安全、自適應(yīng)優(yōu)化ReentrantLock 是代碼手動(dòng)管控的顯式鎖主打靈活可控、功能強(qiáng)大。2.性能取舍低競(jìng)爭(zhēng)場(chǎng)景 synchronized 更優(yōu)高并發(fā)復(fù)雜場(chǎng)景 ReentrantLock 更穩(wěn)定JDK1.6 無絕對(duì)性能碾壓只有場(chǎng)景適配。3.功能取舍synchronized 能力基礎(chǔ)夠用無高級(jí)特性ReentrantLock 擁有超時(shí)鎖、公平鎖、精準(zhǔn)喚醒、狀態(tài)監(jiān)控等高階能力適配復(fù)雜業(yè)務(wù)。4.終極選型原則簡(jiǎn)單場(chǎng)景無腦用 synchronized復(fù)雜高并發(fā)、需要精細(xì)化鎖管控場(chǎng)景必用 ReentrantLock絕不反向選型。