欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#多線程之線程綁定ThreadLocal類

 更新時間:2022年06月17日 11:22:31   作者:天方  
這篇文章介紹了C#多線程之線程綁定ThreadLocal類的用法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

在.Net 4.0的Thread里,新增了線程局部變量(ThreadLocal)類,可以很方便的實現(xiàn)線程專有存儲。

應(yīng)用場景

線程專有存儲應(yīng)被用于這樣的多線程應(yīng)用:它們經(jīng)常訪問那些邏輯上是全局的、而物理上是專有于每個線程的對象。首先我們看如下這樣一個例子

    string errorMessage;

    void Process()
    {
        bool ret = Run();
        if (!ret && needDebug)
        {
            Console.WriteLine(errorMessage);
        }
    }

    bool Run()
    {
        try
        {
            //…-- do something
            return true;
        }
        catch (Exception e)
        {
            errorMessage = e.Message;
            return false;
        }
    }

這個函數(shù)中,Process為主體函數(shù),當(dāng)它調(diào)用Run函數(shù)失敗后,為調(diào)式方便,打出Run函數(shù)的錯誤信息。錯誤信息采用成員變量errorMessage存放,為了減少Run函數(shù)的參數(shù)。

這種通過成員變量errorMessage在函數(shù)間傳遞信息的方式在單線程程序中可以很好的工作,但是在多線程應(yīng)用時卻往往會發(fā)生一些微妙的問題:當(dāng)兩個線程同時執(zhí)行Run函數(shù)時,先執(zhí)行的會被后執(zhí)行的線程覆蓋,導(dǎo)致輸出了錯誤的后執(zhí)行的線程的調(diào)試信息。發(fā)生類似數(shù)據(jù)庫的臟讀錯誤。

解決方案:

最直接的解決方案有兩種:

加鎖:在Process中加鎖,保證沒有兩個線程同時訪問errorMessage

修改Run函數(shù)為bool Run(out string errorMessage)的形式,不通過errorMessage共享數(shù)據(jù),使其支持并發(fā)操作。

這兩種方式都是有效的,但都有一些不足:加鎖時獲取和釋放互斥體有一個不小的開銷,當(dāng)共享的數(shù)據(jù)較多時修改Run函數(shù)會導(dǎo)致Run函數(shù)變得很難看,并且可能會由于改動較大而導(dǎo)致大規(guī)模重構(gòu)。

針對上述兩種方式的不足,人們提出了線程專有存儲的解決方案,使用ThreadLocal類的解決方案如下:

    ThreadLocal<string> errorMessage = new ThreadLocal<string> ();

    void Process()
    {
        bool ret = Run();
        if (!ret && needDebug)
        {
            Console.WriteLine(errorMessage);
        }
    }

    bool Run()
    {
        try
        {
            …- do something
            return true;
        }
        catch (Exception e)
        {
            errorMessage.Value=e.Message;
            return false;
        }
    }

ThreadLocal類在每個線程下都分配一個獨立實例副本,每個線程都只訪問到自己的實例,不會影響其它線程,從而解決讀臟數(shù)據(jù)的問題。

ThreadLocal類也不是什么新概念,在C++、Java等語言的線程庫中都有相關(guān)實現(xiàn),一些語言編譯器實現(xiàn)(如IBM XL FORTRAN)中甚至在語言的層次提供了直接的支持。其實實現(xiàn)的思路很簡單:在ThreadLocal類中有一個哈希表,根據(jù)線程ID為key用于存儲每一個線程的變量的副本。由于現(xiàn)在沒啥相關(guān)資料,并且也是beta版的,我也懶得對.Net中的具體實現(xiàn)和性能進(jìn)一步分析。

和上面的兩種方式相比,線程專有存儲有如下好處:

  • 效率:線程專有存儲可實現(xiàn)成無需對線程專有數(shù)據(jù)進(jìn)行鎖定。例如,通過將errno放入線程專有存儲中,每個線程都可以可靠地設(shè)置和測試該線程中的方法的完成狀態(tài),而無需使用復(fù)雜的同步協(xié)議。這排除了線程中共享數(shù)據(jù)的鎖定開銷,比起獲取和釋放互斥體要更為迅捷。
  • 易于使用:對于應(yīng)用程序員來說,線程專有存儲使用起來很簡單,因為系統(tǒng)開發(fā)者可以通過數(shù)據(jù)抽象或宏來使線程專有存儲的使用在源碼級完全透明化。

但也存在如下缺點:

  • 它鼓勵了(線程安全的)全局變量的使用:許多應(yīng)用不要求多個線程通過公用訪問點來訪問線程專有的數(shù)據(jù)。如果是這樣,數(shù)據(jù)的存儲應(yīng)使只有擁有該數(shù)據(jù)的線程可對它進(jìn)行訪問。
  • 它隱藏了系統(tǒng)的結(jié)構(gòu):線程專有存儲的使用隱藏了應(yīng)用中的對象之間的關(guān)系,可能會導(dǎo)致應(yīng)用更難被理解。

適用性

應(yīng)用有以下特性時可使用線程專有存儲:

  • 應(yīng)用最初的編寫假定了單線程控制,并正在被移植到多線程環(huán)境,而又不能改變現(xiàn)有API
  • 應(yīng)用含有多個占先式線程控制,可以任意的調(diào)度順序并發(fā)執(zhí)行;
  • 每個線程控制調(diào)用一系列方法,這些方法共享只對該線程來說是公用的數(shù)據(jù);
  • 在每個線程中被對象共享的數(shù)據(jù)必須通過一個全局可見的訪問點來訪問;
  • 訪問點"邏輯地"與其他線程共享,但在"物理上" 對于每個線程卻是唯一的;
  • 數(shù)據(jù)在方法間隱式地傳遞,而不是經(jīng)由參數(shù)顯式地傳遞。

理解上面描述的特性對于使用(或不使用)線程專有存儲模式來說是至關(guān)緊要的。例如,UNIX errno變量是一個數(shù)據(jù)例子:(1)邏輯上全局,但是物理上線程專有,以及(2)在方法間隱式地傳遞。

當(dāng)應(yīng)用有以下特性時,不要使用線程專有存儲模式:

  • 多個線程為單個任務(wù)協(xié)同工作,該任務(wù)需要并發(fā)訪問共享數(shù)據(jù)。
    例如,多線程應(yīng)用可以對在內(nèi)存中的數(shù)據(jù)庫并發(fā)地進(jìn)行讀寫。在這樣的情況下,線程必須共享不是線程專有的記錄和表。如果使用線程專有存儲來存儲此數(shù)據(jù)庫,線程就不能共享這些數(shù)據(jù)。因而,對數(shù)據(jù)庫記錄的訪問必須通過同步原語(例如,互斥體)來控制,以使線程能在共享數(shù)據(jù)上協(xié)作。
  • 維護(hù)物理和邏輯上都分離的數(shù)據(jù)要更為直觀和高效。
    例如,通過將數(shù)據(jù)作為參數(shù)顯式地傳遞給所有方法,有可能使線程訪問僅在每個線程中可見的數(shù)據(jù)。在這樣的情況下,線程專有存儲模式有可能是不必要的。

到此這篇關(guān)于C#線程綁定ThreadLocal類的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 淺析C#中結(jié)構(gòu)與類的區(qū)別

    淺析C#中結(jié)構(gòu)與類的區(qū)別

    本文主要對C#結(jié)構(gòu)與類的區(qū)別進(jìn)行簡要分析,文中舉了實例,便于理解,具有很好的參考價值,需要的朋友一起來看下吧
    2016-12-12
  • 帶你復(fù)習(xí)c# 托管和非托管資源

    帶你復(fù)習(xí)c# 托管和非托管資源

    這篇文章主要介紹了c# 托管和非托管資源的相關(guān)資料,文中講解非常細(xì)致,幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • 如何在C#中使用指針

    如何在C#中使用指針

    這篇文章主要介紹了如何在C#中使用指針,文中代碼簡單易懂,幫助大家更好的工作和學(xué)習(xí),感興趣的朋友快來了解下
    2020-06-06
  • C#如何生成唯一訂單號

    C#如何生成唯一訂單號

    這篇文章主要為大家詳細(xì)介紹了C#如何生成唯一訂單號,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • 少見的C# RSA算法

    少見的C# RSA算法

    這篇文章主要介紹了非常少見的C# RSA算法,文章簡單易懂,實例代碼幫助大家更好的學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • 使用?CliWrap?讓C#中的命令行交互(推薦)

    使用?CliWrap?讓C#中的命令行交互(推薦)

    這篇文章主要介紹了使用?CliWrap?讓C#中的命令行交互舉重若輕,這是一個在?.NET?平臺使用的命令行交互工具庫,?通過在C#?中使用?Fluent?的API,?讓命令行交互,感興趣的朋友跟隨小編一起看看吧
    2021-12-12
  • 使用C#實現(xiàn)生成一個綠色文件

    使用C#實現(xiàn)生成一個綠色文件

    這篇文章主要為大家詳細(xì)介紹了如何使用C#實現(xiàn)生成一個綠色文件,可以免去安裝的繁瑣過程,直接運行,非常方便,有需要的小伙伴可以參考一下
    2024-04-04
  • C#中父窗口和子窗口之間控件互操作實例

    C#中父窗口和子窗口之間控件互操作實例

    這篇文章主要介紹了C#中父窗口和子窗口之間控件互操作的方法,實例分析了父窗口與子窗口互操作的技巧,需要的朋友可以參考下
    2015-01-01
  • C#中String.PadRight方法的具體使用

    C#中String.PadRight方法的具體使用

    本文主要介紹了C#中String.PadRight方法的具體使用, 返回一個指定長度的新字符串,其中在當(dāng)前字符串的結(jié)尾填充空格或指定的Unicode字符,下面就來詳細(xì)的了解一下
    2024-01-01
  • C#多線程系列之任務(wù)基礎(chǔ)(二)

    C#多線程系列之任務(wù)基礎(chǔ)(二)

    本文詳細(xì)講解了C#多線程的任務(wù)基礎(chǔ),文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-02-02

最新評論