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

JAVA中Synchronized能否加鎖字符串詳解

 更新時(shí)間:2025年07月04日 10:17:02   作者:拾荒的小海螺  
在Java中Synchronized可以鎖任何對(duì)象,包括字符串,但由于字符串常量在字符串池中是共享的,所以如果多個(gè)線(xiàn)程使用相同的字符串作為鎖對(duì)象,可能會(huì)導(dǎo)致意外的行為,這篇文章主要介紹了JAVA中Synchronized能否加鎖字符串的相關(guān)資料,需要的朋友可以參考下

1、簡(jiǎn)述

在 Java 開(kāi)發(fā)中,synchronized 是一種常見(jiàn)的同步機(jī)制,用于保證線(xiàn)程安全。但是你有沒(méi)有思考過(guò)這樣一個(gè)問(wèn)題:

“synchronized 可以給字符串(String)加鎖嗎?”

答案是:可以,但你應(yīng)該非常小心。

本文將深入剖析這個(gè)問(wèn)題,講清楚背后的機(jī)制、風(fēng)險(xiǎn),并給出實(shí)際建議。

2、synchronized 本質(zhì)上加的是什么鎖?

synchronized 實(shí)際上加的是對(duì)象鎖,也叫監(jiān)視器鎖(monitor lock)。也就是說(shuō):

synchronized (obj) {
    // 臨界區(qū)
}

這段代碼表示:只有獲取到 obj 這個(gè)對(duì)象的監(jiān)視器鎖的線(xiàn)程才能進(jìn)入臨界區(qū)。

因此,只要是一個(gè)對(duì)象,包括字符串實(shí)例,理論上都可以被用作加鎖對(duì)象

3、加鎖字符串——看似可行,實(shí)則隱患巨大

來(lái)看一個(gè)例子:

public class StringLockExample {
    public void doSomething(String lock) {
        synchronized (lock) {
            System.out.println(Thread.currentThread().getName() + " 獲得了鎖:" + lock);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ignored) {}
        }
    }
}

啟動(dòng)多個(gè)線(xiàn)程調(diào)用:

StringLockExample example = new StringLockExample();

Runnable task1 = () -> example.doSomething("LOCK");
Runnable task2 = () -> example.doSomething("LOCK");

new Thread(task1).start();
new Thread(task2).start();

結(jié)果是,兩個(gè)線(xiàn)程會(huì)串行執(zhí)行,因?yàn)榧拥氖峭粋€(gè)字符串 "LOCK" 的鎖。

但問(wèn)題來(lái)了:

字符串是不可變對(duì)象,且 JVM 對(duì)字符串常量具有“字符串池”優(yōu)化機(jī)制(String Interning)!

也就是說(shuō):

String a = "LOCK";
String b = "LOCK";
System.out.println(a == b); // true

兩個(gè)字符串變量實(shí)際上引用的是同一個(gè)對(duì)象。

因此,在你以為傳進(jìn)來(lái)的是不同的字符串時(shí),可能實(shí)際上加的是同一把鎖,或者反過(guò)來(lái)——你以為加的是同一把鎖,其實(shí)不是!

4、字符串加鎖的兩個(gè)典型陷阱

4.1 鎖粒度無(wú)法控制

如果你的鎖是這樣定義的:

synchronized ("user_" + userId)

你以為這是“每個(gè)用戶(hù)一個(gè)鎖”,但實(shí)際上由于字符串拼接會(huì)創(chuàng)建新對(duì)象,每次拼接都是一個(gè)新對(duì)象,鎖根本不會(huì)生效

除非你手動(dòng) .intern() :

synchronized (("user_" + userId).intern())

這又引入了新的問(wèn)題:intern 的對(duì)象存儲(chǔ)在字符串常量池中,頻繁使用可能會(huì)增加內(nèi)存壓力,甚至引發(fā)性能問(wèn)題。

4.2 外部可控鎖對(duì)象

如果你用外部傳入的字符串作為鎖對(duì)象,那你根本無(wú)法控制到底加的是什么鎖。惡意或不規(guī)范調(diào)用者可能傳入一個(gè)常量字符串、空字符串、甚至 null,導(dǎo)致同步行為混亂或拋出異常。

5、安全的替代方案

? 使用自定義鎖對(duì)象

最推薦的方式是自己定義一套鎖策略,例如使用 ConcurrentHashMap 管理鎖對(duì)象:

private final ConcurrentHashMap<String, Object> lockMap = new ConcurrentHashMap<>();

public void doSomething(String key) {
    Object lock = lockMap.computeIfAbsent(key, k -> new Object());

    synchronized (lock) {
        // 臨界區(qū)
    }
}

這種方式可以保證每個(gè)業(yè)務(wù) key 對(duì)應(yīng)一個(gè)明確的鎖對(duì)象,而且不會(huì)誤用常量字符串,鎖粒度清晰可控。

6、使用 Google Guava 的 Interner 實(shí)現(xiàn)更安全的字符串鎖

Interner 是 Google Guava 提供的一個(gè)實(shí)用工具類(lèi),用于實(shí)現(xiàn)“字符串實(shí)例的唯一化”。它的作用類(lèi)似于 String.intern(),但更靈活、可控,不依賴(lài)字符串常量池,避免了 JVM 層級(jí)的內(nèi)存污染和性能隱患。

引入依賴(lài):

<!-- Maven -->
<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>32.1.1-jre</version>
</dependency>

使用示例:

import com.google.common.collect.Interner;
import com.google.common.collect.Interners;

public class GuavaInternerLock {
    private static final Interner<String> interner = Interners.newWeakInterner();

    public void doWork(String key) {
        String internedKey = interner.intern(key);
        synchronized (internedKey) {
            // 同樣 key 的線(xiàn)程會(huì)同步執(zhí)行
            System.out.println("Processing key: " + key);
        }
    }
}

Guava Interner 的優(yōu)勢(shì)

  • 不污染 JVM 的字符串常量池(不像 String.intern())。
  • 可以選擇 Weak 或 Strong 引用,避免內(nèi)存泄漏。
  • 適合在緩存、去重、分布式任務(wù)分片等場(chǎng)景中鎖定“邏輯鍵”

7、總結(jié)

并發(fā)編程中,鎖不是萬(wàn)能的,濫用鎖更是災(zāi)難。本文完整地分析了:

  • synchronized 是否能加鎖字符串(可以,但不推薦);
  • 字符串常量池帶來(lái)的鎖隱患;
  • 如何使用 ObjectConcurrentHashMap 構(gòu)建安全鎖;
  • 如何用 Guava 的 Interner 提供高效、可控的鎖機(jī)制;
  • 方法參數(shù)中加鎖字符串的風(fēng)險(xiǎn)及解決方案。

寫(xiě)高質(zhì)量的并發(fā)代碼,關(guān)鍵是理解鎖的語(yǔ)義、作用域和生命周期。希望這篇文章能幫你在并發(fā)之路上走得更穩(wěn)更遠(yuǎn)。

到此這篇關(guān)于JAVA中Synchronized能否加鎖字符串的文章就介紹到這了,更多相關(guān)JAVA Synchronized加鎖字符串內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JAVA防止重復(fù)提交Web表單的方法

    JAVA防止重復(fù)提交Web表單的方法

    這篇文章主要介紹了JAVA防止重復(fù)提交Web表單的方法,涉及Java針對(duì)表單的相關(guān)處理技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-10-10
  • java 生成有序賬號(hào)的實(shí)現(xiàn)方法

    java 生成有序賬號(hào)的實(shí)現(xiàn)方法

    下面小編就為大家?guī)?lái)一篇java 生成有序賬號(hào)的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-10-10
  • Java線(xiàn)程生命周期圖文詳細(xì)講解

    Java線(xiàn)程生命周期圖文詳細(xì)講解

    在java中,任何對(duì)象都要有生命周期,線(xiàn)程也不例外,它也有自己的生命周期。線(xiàn)程的整個(gè)生命周期可以分為5個(gè)階段,分別是新建狀態(tài)、就緒狀態(tài)、運(yùn)行狀態(tài)、阻塞狀態(tài)和死亡狀態(tài)
    2023-01-01
  • java 實(shí)現(xiàn)MD5加密算法的簡(jiǎn)單實(shí)例

    java 實(shí)現(xiàn)MD5加密算法的簡(jiǎn)單實(shí)例

    這篇文章主要介紹了java 實(shí)現(xiàn)MD5加密算法的簡(jiǎn)單實(shí)例的相關(guān)資料,這里提供實(shí)例幫助大家應(yīng)用這樣的加密算法,需要的朋友可以參考下
    2017-09-09
  • Spring?Boot項(xiàng)目中遇到`if-else`語(yǔ)句七種具體使用方法解析

    Spring?Boot項(xiàng)目中遇到`if-else`語(yǔ)句七種具體使用方法解析

    當(dāng)在Spring?Boot項(xiàng)目中遇到大量if-else語(yǔ)句時(shí),優(yōu)化這些代碼變得尤為重要,因?yàn)樗鼈儾粌H增加了維護(hù)難度,還可能影響應(yīng)用程序的可讀性和性能,以下是七種具體的方法,用于在Spring?Boot項(xiàng)目中優(yōu)化和重構(gòu)if-else語(yǔ)句,感興趣的朋友一起看看吧
    2024-07-07
  • 探索Java中的equals()和hashCode()方法_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    探索Java中的equals()和hashCode()方法_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了探索Java中的equals()和hashCode()方法的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • 利用Spring Social輕松搞定微信授權(quán)登錄的方法示例

    利用Spring Social輕松搞定微信授權(quán)登錄的方法示例

    這篇文章主要介紹了利用Spring Social輕松搞定微信授權(quán)登錄的方法示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-12-12
  • springboot應(yīng)用中使用過(guò)濾器的過(guò)程詳解

    springboot應(yīng)用中使用過(guò)濾器的過(guò)程詳解

    過(guò)濾器通常用于實(shí)現(xiàn)跨切面的功能,例如身份驗(yàn)證、日志記錄、請(qǐng)求和響應(yīng)的修改、性能監(jiān)控等,這篇文章主要介紹了springboot應(yīng)用中使用過(guò)濾器,需要的朋友可以參考下
    2023-06-06
  • java實(shí)現(xiàn)Excel高性能異步導(dǎo)出的完整方案詳解

    java實(shí)現(xiàn)Excel高性能異步導(dǎo)出的完整方案詳解

    在大型電商系統(tǒng)中,數(shù)據(jù)導(dǎo)出是一個(gè)高頻且重要的功能需求,本文將設(shè)計(jì)實(shí)現(xiàn)一套完整的Excel異步導(dǎo)出機(jī)制,通過(guò)注解驅(qū)動(dòng)、任務(wù)隊(duì)列、定時(shí)調(diào)度、消息通知等技術(shù)手段,完美解決了大數(shù)據(jù)量導(dǎo)出的技術(shù)難題,成為項(xiàng)目的重要技術(shù)亮點(diǎn)
    2025-10-10
  • Java中的Spring.factories文件詳解

    Java中的Spring.factories文件詳解

    文章主要介紹了在SpringBoot項(xiàng)目中如何使用spring.factories文件來(lái)注冊(cè)項(xiàng)目依賴(lài)包中的bean,包括SpringFactories的實(shí)現(xiàn)原理、SpringBoot中的SPI機(jī)制、SpringFactories在SpringBoot中的應(yīng)用、Beans的配置等內(nèi)容,從而實(shí)現(xiàn)解耦的擴(kuò)展機(jī)制,感興趣的朋友一起看看吧
    2026-03-03

最新評(píng)論

遂川县| 尼玛县| 黎城县| 临猗县| 赤城县| 徐水县| 确山县| 简阳市| 台中市| 太保市| 贵州省| 民县| 新蔡县| 长兴县| 黄山市| 互助| 县级市| 大化| 天水市| 芒康县| 彭泽县| 萨嘎县| 沛县| 汉阴县| 冷水江市| 南澳县| 宁蒗| 无锡市| 大渡口区| 金华市| 甘洛县| 江源县| 监利县| 吐鲁番市| 武城县| 富川| 额尔古纳市| 鸡西市| 文昌市| 洛阳市| 虞城县|