C 執行緒同步的三類情景分析

2022-09-26 08:06:19 字數 2209 閱讀 2203

c# 已經提供了我們幾種非常好用的類庫如 backgroundworker、thread、task等,借助它們,我們就能夠分分鐘編寫出乙個多執行緒的應用程式。

比如這樣乙個需求:有乙個 winform 窗體,點選按鈕後,會將窗體中的資料匯出到乙個 output.pdf 檔案中。原先的**沒有採用多執行緒技術,所以當點選按鈕後,整個窗體就變成無響應了。為了解決這個問題,可以使用 task.run(()=>);

上面的**看似簡單,卻隱藏著種種危機。如果在匯出的期間,窗體的資料被修改了,那會怎麼樣?如果多個窗體同時匯出到同乙個檔案,又會怎麼樣?

在看完本系列後,你就會清楚了。

有點了解的朋友都知道執行緒同步有多種手段,什麼 mutex、moniter、seamphore、event 等等,我把它們歸為三類,對應三種需要執行緒同步的情景。

情景一:此茅坑有主了

當乙個資源同時被多個執行緒訪問時,有可能會造成資源衝突(尤其是在存在多個寫執行緒的時候)的情景。遇到這種情況,在 c# 中,我們可以使用 interlocked、lock、moniter、spinlock、readwritelockslim、mutex 來處理問題。

什麼情況下會被認為是情景一?

當你設計的類**現靜態變數、io操作時,就會遇到情景一。因為這些資源是由多個物件共享的,不同的執行緒很同時去訪問這些資源時,就可能會出現爭用。

當乙個類被設計成單例,且包含例項變數時,也會遇到情景一。因為例項變數屬於這個單例,當多個執行緒操縱此單例時,該變數可能會被爭用。

當乙個類中的方法呼叫執行緒操作某個例項變數時,也會遇到情景一。

情景二:數量有限,先到先得

情景一強調的是一對多的情形,而在情景二中,資源的數量並不唯一。相比於情景一,情景二側重的是數量上的限制。而用於實現這一需求的類有:semaphore、semaphoreslim。

什麼情況下會被認為是情景二?

當所操作的公共資源存在併發數限制的時候(如資料庫連線、iis連線數限制等),就被認為是情景二。

情景三:我讓你動,你才能動!

情景三關注的是執行緒執行過程中的先後順序,而用於保證這種先後順序的方式就是通過執行緒通訊的方式:manualreseteventslim、manualresetevent、autoresetevent。

什麼情況下會被認為是情景三?

當兩個執行緒所處理的事情有先後的依賴時,比如執行緒二的執行過程依賴執行緒一的執行結果,那就認為是情景三。

不限使用情景

上面的各種方案並不是絕對只限於某一場景,比如 autoresetevent 即可以用於情景三,也可以用於情景一。但是,殺雞焉用牛刀,雖然使用 autoresetevent 能夠實現情景一的需求,但是用不了 autoresetevent 的執行緒通訊能力,同時又會有一些額外的限制(每個執行緒必須保證 wait 和 set 的成對使用,否則乙個執行緒在鎖定資源後就可能被另乙個執行緒解鎖)。

複製** **如下:

lock (m)

//等價於如下方式

autoresetevent.waitone();

//....

autoresetevent.set();

也有朋友說,可以用情景一中的 lock 方案來實現情景三的需求。

autoresetevent autoreset = new autoresetevent(false);

private void button1_click(object sender, eventargs e)

);thread.sleep(1000);//故意gevjgmeu延遲從而保證第二個執行緒是在第乙個執行緒之後才執行

task.run(() =>);}

上面這個例子最終輸出的結果可想而知。此例項說明,不管執行緒實際的執行順序如何,autoresetevent 都能很容易的保證兩個執行緒的執行順序。

如果用 lock 呢?

複製** **如下:

private void button1_click(object sender, eventargs e)

});thread.sleep(1000);//必須人為確保步驟二的執行緒要在步驟一的執行緒之後執行

task.run(() =>

});}

雖然能實現,但是需要花費額外的**去人為保證兩個執行緒的執行順序。

如何在這麼多方案中確定最終所使用的,需要你能對專案的各種情景進行分析,根據實際情景選擇對應的方案,而不至於大材小用。

總 結本文標題: c#執行緒同步的三類情景分析

本文位址: /ruanjian/csharp/115343.html

執行緒同步的情景之三

在情景 一 情景二中,我分別介紹了當多執行緒遇到 資源爭用 限量使用 情形時的解決方案,本篇是本系列的最後一種情形,會介紹幾種用於解決執行緒通訊的方案。情景三 我讓你動,你才能動!大錘 老闆,拿這個手機讓我看看 大錘 這是手機嗎?分別就只是乙個殼子 老闆 呀,這可能是生產上出了問題,我給你換乙個!大...

三 類的複製(C )

內容參考於 21天學通c 第八版 不去糾結c 的原理和細節,從c的角度去學習c 再通過c 專案去加深理解 1.示例1 淺複製及其存在的問題 include include using namespace std class mystring mystring destructor intgetlen...

執行緒同步的情景之一

從本篇文章開始,我將陸續介紹多執行緒中會遇到的三種情況。情景一 此茅坑有主了 大錘 我擦,居然乙個茅坑有兩個人在用。大錘 啊,忍不住了,一起擠擠吧 叫獸 舒坦了,先走了。叫獸按下了沖水開關.嘩啦啦.大錘 你妹啊,衝什麼水啊,衝得我一身 解決方案 為了解決這種混亂的情況,管理員給茅坑加了道門,一次只允...