最新国产好看的视频,伊人天堂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ū)別,并通過流程圖和對(duì)比表格助你做出正確的技術(shù)選型。

一、引言

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

本文將圍繞以下維度展開對(duì)比:

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

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

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

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

三、深入對(duì)比:原理與代碼示例

1. 語法與使用方式

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

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

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

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

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

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

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

2. 鎖的可中斷性

  • synchronized 線程在等待獲取鎖時(shí)不可被中斷Thread.interrupt() 無效,會(huì)一直阻塞)。
  • 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í)間最長(zhǎng)的線程先獲得鎖,但會(huì)降低吞吐量。
Lock fairLock = new ReentrantLock(true);   // 公平鎖
Lock unfairLock = new ReentrantLock(false); // 非公平鎖(默認(rèn))

5. 條件變量(Condition)

synchronized 通過 wait()notify() / notifyAll() 實(shí)現(xiàn)等待/通知,每個(gè)對(duì)象只有一個(gè)等待集。
Lock 可以創(chuàng)建多個(gè) Condition 對(duì)象,實(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)原理簡(jiǎn)述

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

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

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

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 保證(異?;蚍椒ńY(jié)束),不會(huì)遺漏。
  • Lock 的靈活性更高,但手動(dòng)釋放容易出錯(cuò)。

五、流程圖對(duì)比:鎖獲取流程

synchronized 獲取鎖流程

Lock(ReentrantLock)獲取鎖流程

六、性能測(cè)試與選型建議

性能歷史

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

選擇指南

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

七、實(shí)戰(zhàn)代碼對(duì)比:模擬售票系統(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 后,低競(jìng)爭(zhēng)下 synchronized 有偏向鎖優(yōu)化,性能不差;高競(jìng)爭(zhēng)下兩者幾乎持平。

2.“synchronized 不可重入”

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

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

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

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

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

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

最終建議

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

到此這篇關(guān)于Java中Synchronized與Lock鎖機(jī)制的區(qū)別詳解的文章就介紹到這了,更多相關(guān)Java Synchronized與Lock區(qū)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(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中多對(duì)一和一對(duì)多數(shù)據(jù)的處理方法

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

    這篇文章主要介紹了MyBatis中多對(duì)一和一對(duì)多數(shù)據(jù)的處理,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(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)代理 動(dòng)態(tài)代理深入學(xué)習(xí)

    java 靜態(tài)代理 動(dòng)態(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請(qǐng)求體缺失異常原因分析與處理方案

    SpringBoot請(qǐng)求體缺失異常原因分析與處理方案

    這篇文章主要介紹了SpringBoot請(qǐng)求體缺失異常原因分析與處理方案,該異常是因?yàn)閁serController的edit方法缺失了預(yù)期的UserUpdatePwdDTO請(qǐng)求體,產(chǎn)生原因主要由前端未發(fā)送請(qǐng)求體、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()方法及其簡(jiǎn)單的應(yīng)用

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

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

最新評(píng)論

白银市| 河池市| 城固县| 卫辉市| 洪雅县| 吉林市| 克拉玛依市| 肇源县| 鹤岗市| 香河县| 西华县| 奉节县| 类乌齐县| 西藏| 海盐县| 南通市| 嘉义县| 常宁市| 鄂托克旗| 麻城市| 昌黎县| 永和县| 青海省| 阿拉尔市| 青铜峡市| 晋中市| 通辽市| 祁阳县| 辉南县| 兰溪市| 东丰县| 德钦县| 平邑县| 广河县| 香河县| 孝昌县| 蓝田县| 天水市| 灯塔市| 湘阴县| 自治县|