首頁>技術>

只能從內部開啟的一種鎖

不得不說,小明是一個動手能力非常強的同學。學習程式設計就是如此,動手一試,強過所有!

不過小明做的模擬程式並不完善,遇到了一些問題,其中最典型的就是不知道怎麼控制任務序列執行。因為只有一個煮麵的小哥和一個調味的阿姨!但是小明寫的程式中,煮麵的小哥在同時煮很多面,阿姨也同時給很多面調味。

小明發現這顯然沒有很好的模擬出早餐店內的流水線!所以他在今天的的課程開始之前,早早的趕到教室,和我好好的溝通了一陣子。

所以今天的內容,小明已經提前學習了一些了。因為今天的內容,正是關於多執行緒之間,如何解決資源衝突與共享問題的。

課前小明向我表明他所遇到的問題之後,我和小明的聊天如下:

老師:你家有幾個衛生間啊?

小明:一個

老師:衛生間的門,裝鎖了嗎?

小明:裝了

老師:為什麼要裝鎖呢?

小明:老師,我好像有點明白了。。。。

沒錯,程式界,也發明了一種鎖,用於給一些特定資源加鎖,從而避免多個執行緒對於同一個資源的同時操作導致的不一致問題。

例項演示

下面我們看一段簡單的演示例項程式:

class Program{    static long uniqueRes = 0; // 唯一資源    static void DealRes()    {        // 用1萬次加法,模擬大量操作        for (int i = 0; i < 10000; i++)        {            uniqueRes += 1;        }    }    static void Main(string[] args)    {        Console.WriteLine("Hello Thread Locker!");        // 開啟4個執行緒,模擬同時操作資源        var thds = new List<Thread>();        for (int i = 0; i < 4; i++)        {            var t = new Thread(DealRes);            thds.Add(t);            t.Start();        }        foreach (var t in thds)        {            t.Join();        }        Console.WriteLine($"sum: {uniqueRes}");        Console.ReadKey();    }}

程式中,透過4個執行緒模擬對資源的同時操作,每一個執行緒對資源執行1萬次加法,其執行結果如下:

不一致問題

可以看到,執行的結果不可預期,可能正確,也可能不正確,錯的結果各種各樣。這就是多個執行緒,對於一個唯一資源同時操作的惡果。

在實際生產環境中,千萬不能這麼做。

改進例項演示

我看了一眼小明,成竹在胸的樣子,我想他已經知道怎麼解決這個問題了。

其實很簡單,在C#中,使用鎖是很簡單的,我們只需要對DealRes函式進行簡單修改即可:

// 鎖物件static object locker = new object();static void DealRes(){    // 將資源鎖上    lock (locker)    {        // 用1萬次加法,模擬大量操作        for (int i = 0; i < 10000; i++)        {            uniqueRes += 1;        }    }}

多次執行結果如下:

正確的執行結果

小明看到這裡,忍不住發言道:

這樣程式就不是並行運行了,在這一個小例項中,開啟多執行緒沒有任何意義,反而會因為開啟執行緒而浪費資源,降低程式的執行速度。

但是用在早餐店的模擬程式中,就很合適,給煮麵小哥和調味阿姨,分別加上鎖,就可以正常的模擬實際的流水線作業了。

其他同學,紛紛給小明豎起了大拇指。

C#中其他鎖機制

在System.Threading名稱空間下面,還有以下幾個用於控制資源訪問的類:

Monitor

和lock的原理一致,lock正是基於Monitor實現的,是C#中使用最廣泛的一種同步機制。

Mutex

也是一種常用的互斥鎖,相比於Monitor,Mutex可以命名,從而可以實現跨程序之間的同步控制。

ReaderWriterLockSlim

這是一種可以實現寫互斥,讀寫互斥的鎖,可以實現對於資源的讀寫分別控制的鎖。可替代ReaderWriterLock。

SemaphoreSlim

這是一種可以控制資源池的鎖,允許一定數量的執行緒進入訪問共享資源。通常用於限流這類場景。可替代Semaphore。

WaitHandle

這是一種提供等待機制的同步介面,其派生類 EventWaitHandle,AutoResetEvent,ManualResetEvent可以實現基於事件的資源訪問控制。其中ManualResetEventSlim可替代ManualResetEvent。

這時我看向小明,他的臉上,也出現了愁容!這次的鎖有點多,不太好消化的樣子。

小明的臉上,終於又出現了笑容!

聰明的小明同學

踩坑記錄

暫無

下期預告

下面是給同學們準備的乾貨,正在陸續發貨中哦:

多執行緒死鎖問題

Task

Parallel

await/async

Linq與PLinq (ParallelEnumerable)

。。。 。。。

26
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 平臺管理後臺與商家選單資源管理:商家的註冊管理設計