最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中Synchronized與Lock鎖機(jī)制的區(qū)別詳解

 更新時(shí)間:2026年05月07日 09:43:46   作者:身如柳絮隨風(fēng)揚(yáng)  
在?Java?并發(fā)編程中,synchronized?和?Lock?是最常用的兩種鎖機(jī)制,它們都能保證線程安全,但實(shí)現(xiàn)原理、功能特性和性能表現(xiàn)上有顯著差異,下面小編就和大家詳細(xì)介紹一下吧

在 Java 并發(fā)編程中,synchronizedLock 是最常用的兩種鎖機(jī)制。它們都能保證線程安全,但實(shí)現(xiàn)原理、功能特性和性能表現(xiàn)上有顯著差異。本文將帶你徹底搞懂兩者的區(qū)別,并通過流程圖和對比表格助你做出正確的技術(shù)選型。

一、引言

線程安全是并發(fā)編程的核心問題。Java 提供了多種鎖機(jī)制,其中 synchronized 是 JVM 內(nèi)置的關(guān)鍵字,而 Lockjava.util.concurrent.locks 包下的接口(典型實(shí)現(xiàn)如 ReentrantLock)。許多開發(fā)者只知道“Lock 更靈活”,卻不清楚具體靈活在哪里,以及什么場景該用哪個(gè)。

本文將圍繞以下維度展開對比:

  • 語法與使用方式
  • 鎖的獲取與釋放機(jī)制
  • 可中斷性、超時(shí)嘗試
  • 公平性選擇
  • 底層實(shí)現(xiàn)(偏向鎖、輕量級鎖、重量級鎖 vs AQS)
  • 性能表現(xiàn)(JDK 1.6 前后的變化)

最后給出實(shí)戰(zhàn)建議與流程圖,幫助你直觀理解兩者在鎖競爭時(shí)的行為差異。

二、一句話總結(jié)核心區(qū)別(先入為主)

特性synchronizedLock(以 ReentrantLock 為例)
實(shí)現(xiàn)層級JVM 關(guān)鍵字,內(nèi)置語言特性Java 類庫,基于 AQS 的 API
鎖的獲取方式隱式自動獲取/釋放顯式調(diào)用 lock() / unlock()
可中斷性不可中斷(除非拋出異常)支持 lockInterruptibly()
超時(shí)獲取鎖不支持支持 tryLock(timeout, unit)
公平鎖非公平鎖(僅)可公平(構(gòu)造參數(shù))也可非公平
條件變量每個(gè)對象只有一個(gè)等待隊(duì)列(wait/notify)一個(gè) Lock 可綁定多個(gè) Condition
是否可重入是(ReentrantLock 可實(shí)現(xiàn))
鎖釋放方式自動(方法結(jié)束或異常)必須手動在 finally 中釋放
鎖狀態(tài)監(jiān)控無直接 API提供 tryLock()、isHeldByCurrentThread() 等
性能(低競爭)較好(JVM 優(yōu)化,偏向鎖)略差(對象創(chuàng)建開銷)
性能(高競爭)早期較差,JDK 1.6 后改善穩(wěn)定可控,吞吐量有時(shí)更高

三、深入對比:原理與代碼示例

1. 語法與使用方式

synchronized:修飾實(shí)例方法、靜態(tài)方法或代碼塊。

// 實(shí)例方法鎖(當(dāng)前實(shí)例)
public synchronized void method1() { /* 臨界區(qū) */ }

// 靜態(tài)方法鎖(Class 對象)
public static synchronized void method2() { /* 臨界區(qū) */ }

// 代碼塊鎖(自定義對象)
public void method3() {
    synchronized (this) {
        // 臨界區(qū)
    }
}

Lock:需要顯式創(chuàng)建鎖對象,并在 finally 塊中釋放。

Lock lock = new ReentrantLock();
lock.lock();
try {
    // 臨界區(qū)
} finally {
    lock.unlock();   // 必須手動釋放,否則死鎖
}

常見錯(cuò)誤:忘記在 finallyunlock(),導(dǎo)致鎖無法釋放。這也是 synchronized 的“自動釋放”優(yōu)勢所在。

2. 鎖的可中斷性

  • synchronized 線程在等待獲取鎖時(shí)不可被中斷Thread.interrupt() 無效,會一直阻塞)。
  • Lock 提供了 lockInterruptibly(),允許等待鎖的線程響應(yīng)中斷。
lock.lockInterruptibly();  // 等待時(shí)可被中斷
try {
    // ...
} catch (InterruptedException e) {
    // 處理中斷
} finally {
    lock.unlock();
}

3. 超時(shí)獲取鎖(避免死鎖)

synchronized 無法嘗試獲取鎖一段時(shí)間后放棄。LocktryLock(long time, TimeUnit unit) 能實(shí)現(xiàn)非阻塞嘗試:

if (lock.tryLock(1, TimeUnit.SECONDS)) {
    try {
        // 獲取成功
    } finally {
        lock.unlock();
    }
} else {
    // 未獲取到鎖,執(zhí)行其他邏輯
}

4. 公平性

  • synchronized 只支持非公平鎖(等待隊(duì)列中隨機(jī)或按操作系統(tǒng)調(diào)度,可能線程餓死)。
  • ReentrantLock 可選公平鎖:new ReentrantLock(true)。公平鎖保證等待時(shí)間最長的線程先獲得鎖,但會降低吞吐量。
Lock fairLock = new ReentrantLock(true);   // 公平鎖
Lock unfairLock = new ReentrantLock(false); // 非公平鎖(默認(rèn))

5. 條件變量(Condition)

synchronized 通過 wait()、notify() / notifyAll() 實(shí)現(xiàn)等待/通知,每個(gè)對象只有一個(gè)等待集。
Lock 可以創(chuàng)建多個(gè) Condition 對象,實(shí)現(xiàn)更精細(xì)的線程喚醒。

ReentrantLock lock = new ReentrantLock();
Condition notFull  = lock.newCondition();
Condition notEmpty = lock.newCondition();

// 生產(chǎn)者
lock.lock();
try {
    while (隊(duì)列滿) notFull.await();
    // 生產(chǎn)
    notEmpty.signal();
} finally { lock.unlock(); }

四、底層實(shí)現(xiàn)原理簡述

synchronized 的升級過程(JDK 1.6 優(yōu)化)

在 JDK 1.6 之前,synchronized重量級鎖(依賴操作系統(tǒng)的 mutex,用戶態(tài)到內(nèi)核態(tài)切換代價(jià)大)。1.6 之后引入了偏向鎖 → 輕量級鎖 → 重量級鎖的升級過程:

  • 偏向鎖:鎖總是被同一個(gè)線程獲取,無需 CAS。
  • 輕量級鎖:多線程交替執(zhí)行,使用 CAS 嘗試獲取鎖,不阻塞。
  • 重量級鎖:競爭激烈,阻塞線程。

Lock(ReentrantLock)的 AQS 原理

ReentrantLock 基于 AQS(AbstractQueuedSynchronizer),內(nèi)部維護(hù)一個(gè) FIFO 等待隊(duì)列和一個(gè) volatile int state 表示鎖狀態(tài)。通過 CAS 設(shè)置狀態(tài),失敗則加入等待隊(duì)列并阻塞(LockSupport.park())。

兩者底層差異決定:

  • synchronized 的鎖釋放由 JVM 保證(異常或方法結(jié)束),不會遺漏。
  • Lock 的靈活性更高,但手動釋放容易出錯(cuò)。

五、流程圖對比:鎖獲取流程

synchronized 獲取鎖流程

Lock(ReentrantLock)獲取鎖流程

六、性能測試與選型建議

性能歷史

  • JDK 1.5synchronized 性能很差,ReentrantLock 明顯更優(yōu)。
  • JDK 1.6+synchronized 經(jīng)過優(yōu)化(偏向鎖、輕量級鎖、適應(yīng)性自旋),低競爭場景下性能與 Lock 相當(dāng)甚至略好。
  • 高競爭場景:兩者性能差別不大,但 Lock 提供了更多控制(如公平鎖、可中斷)。

選擇指南

場景推薦鎖原因
簡單同步代碼塊,無需高級特性synchronized簡潔、安全、自動釋放
需要嘗試獲取鎖并超時(shí)退出LocktryLock 超時(shí)機(jī)制
需要可中斷的鎖獲取LocklockInterruptibly
需要多個(gè)條件變量(生產(chǎn)者-消費(fèi)者)LockCondition 更靈活
需要公平鎖Locksynchronized 不支持
性能要求極高且競爭極低synchronized偏向鎖開銷小
鎖粗粒度,手動控制釋放時(shí)機(jī)Lock可在不同方法間釋放

七、實(shí)戰(zhàn)代碼對比:模擬售票系統(tǒng)

以下示例展示兩種方式實(shí)現(xiàn)線程安全的余票扣除。

使用 synchronized

class TicketSync {
    private int tickets = 100;
    public synchronized boolean sell() {
        if (tickets <= 0) return false;
        tickets--;
        return true;
    }
}

使用 ReentrantLock

class TicketLock {
    private int tickets = 100;
    private final Lock lock = new ReentrantLock();
    public boolean sell() {
        lock.lock();
        try {
            if (tickets <= 0) return false;
            tickets--;
            return true;
        } finally {
            lock.unlock();
        }
    }
}

八、常見誤區(qū)

1.“Lock 一定比 synchronized 快”

錯(cuò)。JDK 1.6 后,低競爭下 synchronized 有偏向鎖優(yōu)化,性能不差;高競爭下兩者幾乎持平。

2.“synchronized 不可重入”

錯(cuò)。synchronized可重入鎖,同一個(gè)線程可以多次進(jìn)入。

3.“Lock 必須要 try-finally,否則死鎖”

對。若臨界區(qū)拋出異常未釋放鎖,其他線程將永久等待。synchronized 由 JVM 保證釋放。

4.“公平鎖一定比非公平鎖好”

錯(cuò)。公平鎖減少了線程餓死,但上下文切換更頻繁,吞吐量通常更低。

九、總結(jié)與思維導(dǎo)圖

最終建議

  • 優(yōu)先使用 synchronized,除非遇到必須使用 Lock 的場景(如超時(shí)、中斷、多條件)。
  • 永遠(yuǎn)不要自己實(shí)現(xiàn)鎖,使用 JUC 包下的 Lock 實(shí)現(xiàn)。
  • 手動 Lock 時(shí),unlock() 必須放在 finally 塊中。

到此這篇關(guān)于Java中Synchronized與Lock鎖機(jī)制的區(qū)別詳解的文章就介紹到這了,更多相關(guān)Java Synchronized與Lock區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用vscode搭建javaweb項(xiàng)目的詳細(xì)步驟

    使用vscode搭建javaweb項(xiàng)目的詳細(xì)步驟

    我個(gè)人是很喜歡VsCode的,開源免費(fèi)、功能全面,所以為了方便,我把我?guī)缀跛械倪\(yùn)行都集成到了VsCode上來,JavaWeb也不例外,下面這篇文章主要給大家介紹了關(guān)于使用vscode搭建javaweb項(xiàng)目的相關(guān)資料,需要的朋友可以參考下
    2022-11-11
  • java交換排序之奇偶排序?qū)崿F(xiàn)方法

    java交換排序之奇偶排序?qū)崿F(xiàn)方法

    這篇文章主要介紹了java交換排序之奇偶排序?qū)崿F(xiàn)方法,實(shí)例分析了奇偶排序的原理與具體實(shí)現(xiàn)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-02-02
  • MyBatis中多對一和一對多數(shù)據(jù)的處理方法

    MyBatis中多對一和一對多數(shù)據(jù)的處理方法

    這篇文章主要介紹了MyBatis中多對一和一對多數(shù)據(jù)的處理,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-01-01
  • Spring 中 BeanFactoryPostProcessor 的作用和示例源碼分析

    Spring 中 BeanFactoryPostProcessor 的作用和示例源碼分析

    Spring的BeanFactoryPostProcessor是容器初始化的擴(kuò)展接口,允許在Bean實(shí)例化前修改或擴(kuò)展Bean的配置元數(shù)據(jù),本文給大家介紹Spring 中 BeanFactoryPostProcessor 的作用和示例源碼分析,感興趣的朋友一起看看吧
    2025-03-03
  • java 靜態(tài)代理 動態(tài)代理深入學(xué)習(xí)

    java 靜態(tài)代理 動態(tài)代理深入學(xué)習(xí)

    代理模式是常用的java設(shè)計(jì)模式,特征是代理類與委托類有同樣的接口,代理類主要負(fù)責(zé)為委托類預(yù)處理消息、過濾消息、把消息轉(zhuǎn)發(fā)給委托類,以及事后處理消息等,需要的朋友可以參考下
    2012-11-11
  • JavaSE文件操作工具類FileUtil詳解

    JavaSE文件操作工具類FileUtil詳解

    這篇文章主要為大家詳細(xì)介紹了JavaSE系列之文件操作工具類FileUtil,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • DoytoQuery中的查詢映射方案詳解

    DoytoQuery中的查詢映射方案詳解

    這篇文章主要為大家介紹了DoytoQuery中的查詢映射方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • SpringBoot請求體缺失異常原因分析與處理方案

    SpringBoot請求體缺失異常原因分析與處理方案

    這篇文章主要介紹了SpringBoot請求體缺失異常原因分析與處理方案,該異常是因?yàn)閁serController的edit方法缺失了預(yù)期的UserUpdatePwdDTO請求體,產(chǎn)生原因主要由前端未發(fā)送請求體、Content-Type設(shè)置錯(cuò)誤或后端缺少@RequestBody注解導(dǎo)致,需要的朋友可以參考下
    2025-10-10
  • SpringBoot實(shí)現(xiàn)數(shù)據(jù)加密脫敏的示例代碼

    SpringBoot實(shí)現(xiàn)數(shù)據(jù)加密脫敏的示例代碼

    這篇文章主要為大家學(xué)習(xí)介紹了SpringBoot如何利用注解+反射+AOP實(shí)現(xiàn)數(shù)據(jù)加密脫敏的功能,文中的示例代碼講解詳細(xì),需要的可以參考一下
    2023-08-08
  • 關(guān)于重寫equals()方法和hashCode()方法及其簡單的應(yīng)用

    關(guān)于重寫equals()方法和hashCode()方法及其簡單的應(yīng)用

    這篇文章主要介紹了關(guān)于重寫equals()方法和hashCode()方法及其簡單的應(yīng)用,網(wǎng)上的知識有些可能是錯(cuò)誤的,關(guān)于?equals()?方法的理解,大家討論不一樣,需要的朋友可以參考下
    2023-04-04

最新評論

成安县| 永年县| 瑞金市| 河间市| 福安市| 周至县| 涞源县| 游戏| 东乡| 巴彦县| 潜山县| 贵港市| 灵山县| 绩溪县| 上高县| 卫辉市| 克东县| 九寨沟县| 神池县| 五峰| 察哈| 高阳县| 陆川县| 政和县| 中牟县| 石狮市| 绥棱县| 天祝| 沾化县| 阿尔山市| 景洪市| 石渠县| 平阴县| 佳木斯市| 阿克苏市| 陆良县| 长子县| 远安县| 富宁县| 高邮市| 城步|