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

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

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

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

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

一、背景:單例模式 + 多線程環(huán)境

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

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

二、簡單加鎖的問題:性能瓶頸

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

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

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

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

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

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

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

  1. 第一次檢查(無鎖):如果 instance != null,直接返回(絕大多數(shù)情況走這里,快?。?/li>
  2. 如果 instance == null,說明可能需要?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)               // 第一次檢查(無鎖)
        {
            lock (lockObj)
            {
                if (instance == null)       // 第二次檢查(有鎖)
                    instance = new Singleton();
            }
        }
        return instance;
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • 禁止指令重排序
  • 保證內(nèi)存可見性(一個(gè)線程寫入,其他線程立即可見)
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)線程安全的雙重檢查邏輯
  • 代碼更簡潔、不易出錯(cuò)
  • 性能同樣優(yōu)秀

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

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

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

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

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

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

一、背景:單例模式 + 多線程環(huán)境

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

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

二、簡單加鎖的問題:性能瓶頸

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

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

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

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

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

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

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

  1. 第一次檢查(無鎖):如果 instance != null,直接返回(絕大多數(shù)情況走這里,快?。?/li>
  2. 如果 instance == null,說明可能需要?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)               // 第一次檢查(無鎖)
        {
            lock (lockObj)
            {
                if (instance == null)       // 第二次檢查(有鎖)
                    instance = new Singleton();
            }
        }
        return instance;
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • 禁止指令重排序
  • 保證內(nèi)存可見性(一個(gè)線程寫入,其他線程立即可見)
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)線程安全的雙重檢查邏輯
  • 代碼更簡潔、不易出錯(cuò)
  • 性能同樣優(yōu)秀

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

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

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

?? 一句話總結(jié):雙重檢查鎖是在“懶加載 + 線程安全 + 高性能”三者之間取得的最佳平衡(在沒有 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ù)用原則,文中通過示例代碼介紹的非常詳細(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#使用LibUsbDotNet實(shí)現(xiàn)USB設(shè)備檢測

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

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

    這篇文章主要介紹了C#簡單嵌套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ì)教程,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-04-04
  • C#中struct, class的使用區(qū)別

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

    類和結(jié)構(gòu)體是C#中用于定義數(shù)據(jù)類型的關(guān)鍵字,它們?cè)趦?nè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)論

鸡泽县| 新和县| 明星| 京山县| 荆门市| 富蕴县| 汝南县| 河源市| 共和县| 吉林省| 新巴尔虎左旗| 肥乡县| 尼勒克县| 鹿邑县| 株洲县| 内江市| 成武县| 罗山县| 涿鹿县| 澄城县| 高要市| 乌拉特后旗| 连云港市| 衡水市| 通州区| 茌平县| 孝昌县| 浦北县| 舞阳县| 濮阳市| 永州市| 垣曲县| 古丈县| 吉木萨尔县| 浦北县| 寻甸| 凤庆县| 德化县| 九龙县| 航空| 民勤县|