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

C#使用雙檢鎖的示例代碼

 更新時(shí)間:2025年12月01日 15:37:48   作者:她說(shuō)彩禮65萬(wàn)  
本文主要介紹了C#使用雙檢鎖的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

為什么要使用雙重檢查鎖定(Double-Checked Locking, DCL)”?答案的核心在于:在保證線程安全的前提下,盡可能提高性能。

下面我們從背景、問(wèn)題、解決方案三個(gè)層面來(lái)解釋。

一、背景:?jiǎn)卫J?+ 多線程環(huán)境

在多線程程序中,如果多個(gè)線程同時(shí)調(diào)用 getInstance(),而實(shí)例尚未創(chuàng)建,就可能出現(xiàn) 多個(gè)線程同時(shí)進(jìn)入 if (instance == null) 判斷,從而創(chuàng)建多個(gè)實(shí)例 —— 這違反了單例的“唯一性”原則。

所以,必須保證線程安全。

二、簡(jiǎn)單加鎖的問(wèn)題:性能瓶頸

最直接的線程安全方案是給整個(gè) getInstance() 方法加鎖:

public static Singleton Instance
{
    get
    {
        lock (lockObj)
        {
            if (instance == null)
                instance = new Singleton();
            return instance;
        }
    }
}

? 安全
? 但每次調(diào)用都要加鎖!即使實(shí)例早已創(chuàng)建,后續(xù)所有訪問(wèn)仍要競(jìng)爭(zhēng)鎖,性能開(kāi)銷大。

在高并發(fā)場(chǎng)景下,這會(huì)成為明顯的性能瓶頸。

三、雙重檢查鎖定(DCL)的思路

目標(biāo):只在“第一次創(chuàng)建實(shí)例時(shí)”加鎖,之后直接返回已有實(shí)例,避免無(wú)謂的同步開(kāi)銷。

實(shí)現(xiàn)邏輯:

  1. 第一次檢查(無(wú)鎖):如果 instance != null,直接返回(絕大多數(shù)情況走這里,快?。?/li>
  2. 如果 instance == null,說(shuō)明可能需要?jiǎng)?chuàng)建,此時(shí)加鎖。
  3. 第二次檢查(有鎖):再次判斷 instance == null,防止多個(gè)線程在第一次檢查后都進(jìn)入臨界區(qū),導(dǎo)致重復(fù)創(chuàng)建。
public static Singleton Instance
{
    get
    {
        if (instance == null)               // 第一次檢查(無(wú)鎖)
        {
            lock (lockObj)
            {
                if (instance == null)       // 第二次檢查(有鎖)
                    instance = new Singleton();
            }
        }
        return instance;
    }
}

四、為什么需要“兩次”檢查?

假設(shè)只有一次檢查(只在鎖內(nèi)判斷):

lock (lockObj)
{
    if (instance == null)
        instance = new Singleton();
}

→ 這樣雖然安全,但每次都要加鎖,失去了懶加載的性能優(yōu)勢(shì)。

而如果只在鎖外檢查一次:

if (instance == null)
{
    lock (lockObj)
    {
        instance = new Singleton(); // ? 沒(méi)有第二次檢查!
    }
}

→ 問(wèn)題:線程 A 和 B 同時(shí)通過(guò) if (instance == null),A 先拿到鎖創(chuàng)建了實(shí)例,B 等待后拿到鎖,又創(chuàng)建一次!破壞單例!

? 所以,“雙重檢查”是為了:

  • 避免重復(fù)創(chuàng)建(第二次檢查)
  • 避免不必要的加鎖(第一次檢查)

五、內(nèi)存可見(jiàn)性問(wèn)題:為什么需要volatile

在 C#、Java 等語(yǔ)言中,對(duì)象創(chuàng)建不是原子操作,可能被重排序:

instance = new Singleton();
// 實(shí)際可能分解為:
// 1. 分配內(nèi)存
// 2. 初始化對(duì)象
// 3. 將引用賦值給 instance

但編譯器或 CPU 可能將步驟 2 和 3 重排序 → 先賦值引用,再初始化!

結(jié)果:線程 A 還沒(méi)初始化完,線程 B 就看到 instance != null,拿到一個(gè)未完全構(gòu)造的對(duì)象,導(dǎo)致程序崩潰!

? 解決方案:使用 volatile 關(guān)鍵字(C# / Java)

  • 禁止指令重排序
  • 保證內(nèi)存可見(jiàn)性(一個(gè)線程寫(xiě)入,其他線程立即可見(jiàn))
private static volatile Singleton instance;

?? 在 C++ 中需使用 std::atomic 或內(nèi)存屏障;在 .NET 中 volatile 足夠。

六、現(xiàn)代替代方案:Lazy<T>

雖然 DCL 是經(jīng)典解法,但在現(xiàn)代 C# 中,更推薦使用 Lazy<T>:

private static readonly Lazy<Singleton> lazy = 
    new Lazy<Singleton>(() => new Singleton());

public static Singleton Instance => lazy.Value;
  • 內(nèi)部已實(shí)現(xiàn)線程安全的雙重檢查邏輯
  • 代碼更簡(jiǎn)潔、不易出錯(cuò)
  • 性能同樣優(yōu)秀

但理解 DCL 的原理仍然非常重要,尤其在面試、底層開(kāi)發(fā)或跨語(yǔ)言場(chǎng)景中。

總結(jié):為什么要用雙檢鎖?

目標(biāo)說(shuō)明
? 線程安全防止多線程創(chuàng)建多個(gè)實(shí)例
? 懶加載實(shí)例只在首次使用時(shí)創(chuàng)建
? 高性能實(shí)例創(chuàng)建后,后續(xù)訪問(wèn)無(wú)需加鎖
? 避免重排序風(fēng)險(xiǎn)配合 volatile 保證正確性

?? 一句話總結(jié):雙重檢查鎖是在“懶加載 + 線程安全 + 高性能”三者之間取得的最佳平衡(在沒(méi)有 Lazy<T> 的年代尤其重要)。

如果你在寫(xiě) C#,可以直接用 Lazy<T>;但理解 DCL 背后的并發(fā)思想,對(duì)成為一名優(yōu)秀開(kāi)發(fā)者至關(guān)重要。這是一個(gè)非常好的問(wèn)題!“為什么要使用雙重檢查鎖定(Double-Checked Locking, DCL)”?答案的核心在于:在保證線程安全的前提下,盡可能提高性能。

下面我們從背景、問(wèn)題、解決方案三個(gè)層面來(lái)解釋。

一、背景:?jiǎn)卫J?+ 多線程環(huán)境

在多線程程序中,如果多個(gè)線程同時(shí)調(diào)用 getInstance(),而實(shí)例尚未創(chuàng)建,就可能出現(xiàn) 多個(gè)線程同時(shí)進(jìn)入 if (instance == null) 判斷,從而創(chuàng)建多個(gè)實(shí)例 —— 這違反了單例的“唯一性”原則。

所以,必須保證線程安全。

二、簡(jiǎn)單加鎖的問(wèn)題:性能瓶頸

最直接的線程安全方案是給整個(gè) getInstance() 方法加鎖:

public static Singleton Instance
{
    get
    {
        lock (lockObj)
        {
            if (instance == null)
                instance = new Singleton();
            return instance;
        }
    }
}

? 安全
? 但每次調(diào)用都要加鎖!即使實(shí)例早已創(chuàng)建,后續(xù)所有訪問(wèn)仍要競(jìng)爭(zhēng)鎖,性能開(kāi)銷大。

在高并發(fā)場(chǎng)景下,這會(huì)成為明顯的性能瓶頸。

三、雙重檢查鎖定(DCL)的思路

目標(biāo):只在“第一次創(chuàng)建實(shí)例時(shí)”加鎖,之后直接返回已有實(shí)例,避免無(wú)謂的同步開(kāi)銷。

實(shí)現(xiàn)邏輯:

  1. 第一次檢查(無(wú)鎖):如果 instance != null,直接返回(絕大多數(shù)情況走這里,快?。?/li>
  2. 如果 instance == null,說(shuō)明可能需要?jiǎng)?chuàng)建,此時(shí)加鎖。
  3. 第二次檢查(有鎖):再次判斷 instance == null,防止多個(gè)線程在第一次檢查后都進(jìn)入臨界區(qū),導(dǎo)致重復(fù)創(chuàng)建。
public static Singleton Instance
{
    get
    {
        if (instance == null)               // 第一次檢查(無(wú)鎖)
        {
            lock (lockObj)
            {
                if (instance == null)       // 第二次檢查(有鎖)
                    instance = new Singleton();
            }
        }
        return instance;
    }
}

四、為什么需要“兩次”檢查?

假設(shè)只有一次檢查(只在鎖內(nèi)判斷):

lock (lockObj)
{
    if (instance == null)
        instance = new Singleton();
}

→ 這樣雖然安全,但每次都要加鎖,失去了懶加載的性能優(yōu)勢(shì)。

而如果只在鎖外檢查一次:

if (instance == null)
{
    lock (lockObj)
    {
        instance = new Singleton(); // ? 沒(méi)有第二次檢查!
    }
}

→ 問(wèn)題:線程 A 和 B 同時(shí)通過(guò) if (instance == null),A 先拿到鎖創(chuàng)建了實(shí)例,B 等待后拿到鎖,又創(chuàng)建一次!破壞單例!

? 所以,“雙重檢查”是為了:

  • 避免重復(fù)創(chuàng)建(第二次檢查)
  • 避免不必要的加鎖(第一次檢查)

五、內(nèi)存可見(jiàn)性問(wèn)題:為什么需要volatile

在 C#、Java 等語(yǔ)言中,對(duì)象創(chuàng)建不是原子操作,可能被重排序:

instance = new Singleton();
// 實(shí)際可能分解為:
// 1. 分配內(nèi)存
// 2. 初始化對(duì)象
// 3. 將引用賦值給 instance

但編譯器或 CPU 可能將步驟 2 和 3 重排序 → 先賦值引用,再初始化!

結(jié)果:線程 A 還沒(méi)初始化完,線程 B 就看到 instance != null,拿到一個(gè)未完全構(gòu)造的對(duì)象,導(dǎo)致程序崩潰!

? 解決方案:使用 volatile 關(guān)鍵字(C# / Java)

  • 禁止指令重排序
  • 保證內(nèi)存可見(jiàn)性(一個(gè)線程寫(xiě)入,其他線程立即可見(jiàn))
private static volatile Singleton instance;

?? 在 C++ 中需使用 std::atomic 或內(nèi)存屏障;在 .NET 中 volatile 足夠。

六、現(xiàn)代替代方案:Lazy<T>

雖然 DCL 是經(jīng)典解法,但在現(xiàn)代 C# 中,更推薦使用 Lazy<T>:

private static readonly Lazy<Singleton> lazy = 
    new Lazy<Singleton>(() => new Singleton());

public static Singleton Instance => lazy.Value;
  • 內(nèi)部已實(shí)現(xiàn)線程安全的雙重檢查邏輯
  • 代碼更簡(jiǎn)潔、不易出錯(cuò)
  • 性能同樣優(yōu)秀

但理解 DCL 的原理仍然非常重要,尤其在面試、底層開(kāi)發(fā)或跨語(yǔ)言場(chǎng)景中。

總結(jié):為什么要用雙檢鎖?

目標(biāo)說(shuō)明
? 線程安全防止多線程創(chuàng)建多個(gè)實(shí)例
? 懶加載實(shí)例只在首次使用時(shí)創(chuàng)建
? 高性能實(shí)例創(chuàng)建后,后續(xù)訪問(wèn)無(wú)需加鎖
? 避免重排序風(fēng)險(xiǎn)配合 volatile 保證正確性

?? 一句話總結(jié):雙重檢查鎖是在“懶加載 + 線程安全 + 高性能”三者之間取得的最佳平衡(在沒(méi)有 Lazy<T> 的年代尤其重要)。

到此這篇關(guān)于C#使用雙檢鎖的示例代碼的文章就介紹到這了,更多相關(guān)C# 雙檢鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C#面向?qū)ο笤O(shè)計(jì)原則之組合/聚合復(fù)用原則

    C#面向?qū)ο笤O(shè)計(jì)原則之組合/聚合復(fù)用原則

    這篇文章介紹了C#面向?qū)ο笤O(shè)計(jì)原則之組合/聚合復(fù)用原則,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • C#靜態(tài)構(gòu)造函數(shù)用法實(shí)例分析

    C#靜態(tài)構(gòu)造函數(shù)用法實(shí)例分析

    這篇文章主要介紹了C#靜態(tài)構(gòu)造函數(shù)用法,以實(shí)例形式較為詳細(xì)的分析了C#靜態(tài)構(gòu)造函數(shù)的用途、實(shí)現(xiàn)方法及使用技巧,需要的朋友可以參考下
    2015-06-06
  • C#中winform使用相對(duì)路徑讀取文件的方法

    C#中winform使用相對(duì)路徑讀取文件的方法

    這篇文章主要介紹了C#中winform使用相對(duì)路徑讀取文件的方法,實(shí)例分析了C#使用相對(duì)路徑讀取文件的技巧與實(shí)際應(yīng)用,需要的朋友可以參考下
    2015-01-01
  • C#確保只有一個(gè)實(shí)例在運(yùn)行的方法

    C#確保只有一個(gè)實(shí)例在運(yùn)行的方法

    這篇文章主要介紹了C#確保只有一個(gè)實(shí)例在運(yùn)行的方法,涉及C#進(jìn)程操作的相關(guān)技巧,需要的朋友可以參考下
    2015-05-05
  • webBrowser代理設(shè)置c#代碼

    webBrowser代理設(shè)置c#代碼

    本文將介紹C# 為webBrowser設(shè)置代理實(shí)現(xiàn)代碼,需要了解的朋友可以參考下
    2012-11-11
  • C#使用LibUsbDotNet實(shí)現(xiàn)USB設(shè)備檢測(cè)

    C#使用LibUsbDotNet實(shí)現(xiàn)USB設(shè)備檢測(cè)

    C#?LibUsbDotNet是一個(gè).NET平臺(tái)上的庫(kù),用于訪問(wèn)USB設(shè)備,它封裝了Linux下的libusb庫(kù),LibUsbDotNet提供了一個(gè)簡(jiǎn)單的API,開(kāi)發(fā)者可以利用這個(gè)庫(kù)在C#中操作USB設(shè)備,本文介紹了C#使用LibUsbDotNet實(shí)現(xiàn)USB設(shè)備檢測(cè),需要的朋友可以參考下
    2024-07-07
  • C#簡(jiǎn)單嵌套flash讀取數(shù)據(jù)的實(shí)現(xiàn)代碼

    C#簡(jiǎn)單嵌套flash讀取數(shù)據(jù)的實(shí)現(xiàn)代碼

    這篇文章主要介紹了C#簡(jiǎn)單嵌套flash讀取數(shù)據(jù)的實(shí)現(xiàn)代碼,有需要的朋友可以參考一下
    2013-11-11
  • C#判斷字符串中內(nèi)容是否為純數(shù)字的詳細(xì)教程

    C#判斷字符串中內(nèi)容是否為純數(shù)字的詳細(xì)教程

    在進(jìn)行C#編程時(shí)候,有的時(shí)候我們需要判斷一個(gè)字符串是否是數(shù)字字符串,下面這篇文章主要給大家介紹了關(guān)于C#判斷字符串中內(nèi)容是否為純數(shù)字的詳細(xì)教程,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-04-04
  • C#中struct, class的使用區(qū)別

    C#中struct, class的使用區(qū)別

    類和結(jié)構(gòu)體是C#中用于定義數(shù)據(jù)類型的關(guān)鍵字,它們?cè)趦?nèi)存分配、生命周期管理、性能等方面存在顯著差異,下面就來(lái)詳細(xì)的介紹一下這兩者的區(qū)別,感興趣的可以了解一下
    2026-01-01
  • Unity3D Shader實(shí)現(xiàn)動(dòng)態(tài)屏幕遮罩

    Unity3D Shader實(shí)現(xiàn)動(dòng)態(tài)屏幕遮罩

    這篇文章主要為大家詳細(xì)介紹了Unity3D Shader實(shí)現(xiàn)動(dòng)態(tài)屏幕遮罩效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-02-02

最新評(píng)論

贵港市| 洮南市| 武冈市| 聊城市| 牡丹江市| 天门市| 博客| 英吉沙县| 油尖旺区| 金山区| 文化| 宜都市| 上高县| 凤台县| 宁南县| 乡宁县| 萍乡市| 玛多县| 白城市| 木兰县| 五家渠市| 古蔺县| 忻州市| 永平县| 遵义县| 扎兰屯市| 安岳县| 漠河县| 新化县| 进贤县| 盘山县| 延边| 巫山县| 庄浪县| 霍城县| 县级市| 萝北县| 新乐市| 普兰店市| 东明县| 隆化县|