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