.NET多執行緒操作需要考慮的兩大因素
執行緒管理現在變得越來越容易了。在.NET架構中,你可以從執行緒池中獲取執行緒。執行緒池是一個生成執行緒的工廠,如果它已經生成了一定數量的執行緒且還沒有被破壞的話,對它的呼叫會被阻止。但是,如何確保不會有太多的執行緒在規定時間內執行?畢竟,如果每個執行緒能夠佔用一個CPU核的100%,那麼有超過CPU核數量的執行緒執行,只會導致作業系統啟動執行緒時間分配,這將導致上下文切換和低效率執行。換句話說,同一核上的兩個執行緒不會以兩倍的時長完成,可能需要用兩倍再加10 %左右的時間來完成。與一個執行緒相比較的話,三個執行緒在同一核上想佔用100 %的CPU使用率可能會需要3.25——3.5倍的時長來完成。我的經驗是,每個核都有多個執行緒試圖佔用100 %的CPU,但它們都不能達到目標。
所以,要怎樣分配正在執行的執行緒數量呢?
有一個辦法是線上程之間建立一個共享的旗語物件。線上程開始執行前,它會嘗試呼叫旗語的WaitOne模式,並在完成後釋放旗語。對CPU的核數量設定旗語限制,(使用EnvironmentProcessorCount功能限定);這將防止您的系統在同一時間執行的執行緒數多於核數量。與此同時,從執行緒池中拉出執行緒將確保您不會在同一時間建立過多執行緒。如果一次建立執行緒過多,即使他們並沒執行,那也是浪費系統資源。因為每個執行緒都要消耗資源。使用旗語的一般模式如下所示:
static Semaphore threadBlocker;
static void Execute(object state)
{ threadBlocker.WaitOne(); //Do work threadBlocker.Release(); }
static void RunThreads()
{ threadBlocker = new Semaphore(0, Environment.ProcessorCount); for (int x = 0; x <= 2000; x++) {ThreadPool.QueueUserWorkItem(new WaitCallback (Execute)); } }
當然還有其他一些辦法可以解決這一問題。前一段時間我想要保持物件的一份〈T〉清單。每個物件代表每個工人部件的完整狀態。執行和完成時,工人部件都會被填入資料。並且他會設定某個功能以指示任務完成。主執行緒將掃描物件清單,如果執行的執行緒數量足夠少,就開始執行另一個。說實話,雖然這個方法可行,但對於程式碼和除錯來說這絕對是個噩夢,所以我一點也不推薦。
資料完整性
總體而言,在資料完整性方面,你要擔心的問題是競爭條件和死鎖。多個執行緒試圖在同一時間更新相同的物件就會造成競爭條件,這將招致麻煩。想象一下如果使用下面這段程式碼:
int x = 5;
x = x + 10;
現在,如果執行緒A和執行緒B在同一時間執行此程式碼,將會發生什麼情況?它可以執行得很好?還是會出現什麼問題?如果出現問題,又是些怎樣的問題呢?每個執行緒都不會一次執行全部語句。因此,我們可以按照以下順序操作:
1. Thread A retrieves the value of x (5).
2. Thread B retrieves the value of x (5).
3. Thread A assigns x + 10 (15) to x.
4. Thread B assigns x + 10 (15) to x.
5. x is now equal to 15.
或者,相同的程式碼可以按照不同的順序:
1. Thread A retrieves the value of x (5).
2. Thread A assigned x = 10 (15) to x.
3. Thread B retrieves the value of x (15).
4. Thread B assigns x + 10 (25) to x.
5. x is now equal to 25.
在.NET架構中,最簡單也最常見的解決競爭條件的方法是使用“臨界區”。而在VB.NET中,該語句是“加鎖”,並在C#中是“鎖定”,這兩種語句都是把物件作為引數。其他嘗試鎖定相同物件例項使用的臨界區(包括上文所指的)會阻止執行直到鎖定解除,這樣每次就只有一個臨界區執行。我們先前舉例的一段程式碼現在看起來是這樣的:
int x = 5;
object lockObject = new object();
Monitor.Enter(lockObject);
x = x + 10;
Monitor.Exit(lockObject);
什麼是監控器可以提供而臨界區做不到的呢?答案是沒有。除非你在解鎖後需要更細粒度的控制權。有些複雜的程式碼可能需要鎖定或長或短的一段時間,這都取決於執行的情況,比方一個變數的值。在這種情況下,選擇監控器要比需選擇臨界區更合適。
另一個值得關注的有關資料完整性的問題是死鎖。當多個執行緒鎖定資源導致它們都不能夠繼續執行時,就會出現死鎖。例如:
Thread A:
Monitor.Enter(object1);
Monitor.Enter(object2);
//Do work
Monitor.Exit(object1);
Monitor.Exit(object2);
Thread B:
Monitor.Enter(object2);
Monitor.Enter(object1);
//Do work
Monitor.Exit(object1);
Monitor.Exit(object2);
如果執行緒A和執行緒B都呼叫它們的第一段語句並且同時完成執行,那它們都無法呼叫它們的第二段語句——這就是一個死鎖。所以編寫程式碼的時候細心,要仔細想清楚怎樣編寫程式碼才更有利。死鎖的發生常見於新手,因為他們過分設定鎖定把它變得太詳細了。如果程式碼被巢狀鎖定通常表明需要對編寫的程式碼加以認真檢查。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-545264/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- oracle 中並行度的設定需要考慮的因素Oracle並行
- 資料庫備份策略需要考慮的幾大因素資料庫
- 多執行緒考點執行緒
- 多執行緒操作執行緒
- 伺服器託管需要考慮這些因素伺服器
- .NET多執行緒(五)非同步操作執行緒非同步
- .NET 多執行緒執行緒
- 多執行緒的執行緒狀態及相關操作執行緒
- 【java】【多執行緒】建立執行緒的兩種常用方式(2)Java執行緒
- windows多執行緒--原子操作Windows執行緒
- PHPPthread多執行緒操作PHPthread執行緒
- .net使用Task多執行緒執行任務 .net限制執行緒數量執行緒
- .NET多執行緒程式設計(1):多工和多執行緒 (轉)執行緒程式設計
- 多執行緒-多執行緒兩種方式的圖解比較及區別執行緒圖解
- .NET下多執行緒初探執行緒
- 嵌入式開發微處理器選型需要考慮的因素
- NSThread與多執行緒操作thread執行緒
- 大資料分析平臺選擇考慮哪些因素大資料
- .NET多執行緒程式設計(3):執行緒同步 (轉)執行緒程式設計
- 選用住宅代理時要考慮的因素
- 實際技術選型的考慮因素
- 團隊結構應該考慮的因素
- iOS APP開發公司需要考慮的因素有哪些? 北京銳智互動iOSAPP
- 2023 年 MQTT Broker 選型時需要考慮的 7 個因素MQQT
- 實戰.Net多執行緒(一)執行緒
- 實戰.Net多執行緒(二)執行緒
- 實戰.Net多執行緒(三)執行緒
- 實戰.Net多執行緒(四)執行緒
- 【Java】【多執行緒】兩個執行緒間的通訊、wait、notify、notifyAllJava執行緒AI
- 敲開阿里大門的執行緒、多執行緒和執行緒池面試專題阿里執行緒面試
- 多執行緒和多執行緒同步執行緒
- 遊戲開服導量,需要考慮的三大需求遊戲
- 學軟體測試選培訓機構需要考慮哪些因素
- SVD矩陣分解考慮時間因素矩陣
- 在netty3.x中存在兩種執行緒:boss執行緒和worker執行緒。Netty執行緒
- 執行緒以及多執行緒,多程式的選擇執行緒
- 多執行緒-多執行緒常見的面試題執行緒面試題
- 多執行緒【執行緒池】執行緒