分析.NET上執(zhí)行多線程應(yīng)該注意的兩點(diǎn)_.Net教程
推薦:脫離.Net Framework框架運(yùn)行.Net程序.Net 框架目前逐步在普及了,仍然有很多人在尋找如何讓.Net程序脫離.NET框架的方法。 現(xiàn)成的工具有 Xenocode 的postbuidle或者vas,還有 Salamander .NET Linker . 另外還有 MaxToCode 作者以前做的 framework linker. 以及一些支持注冊(cè)表模擬和文件模擬的打
線程管理
線程管理現(xiàn)在變得越來(lái)越容易了。在.NET架構(gòu)中,你可以從線程池中獲取線程。線程池是一個(gè)生成線程的工廠,如果它已經(jīng)生成了一定數(shù)量的線程且還沒(méi)有被破壞的話,對(duì)它的調(diào)用會(huì)被阻止。但是,如何確保不會(huì)有太多的線程在規(guī)定時(shí)間內(nèi)運(yùn)行?畢竟,如果每個(gè)線程能夠占用一個(gè)CPU核的100%,那么有超過(guò)CPU核數(shù)量的線程運(yùn)行,只會(huì)導(dǎo)致操作系統(tǒng)啟動(dòng)線程時(shí)間分配,這將導(dǎo)致上下文切換和低效率運(yùn)行。換句話說(shuō),同一核上的兩個(gè)線程不會(huì)以兩倍的時(shí)長(zhǎng)完成,可能需要用兩倍再加10%左右的時(shí)間來(lái)完成。與一個(gè)線程相比較的話,三個(gè)線程在同一核上想占用100%的CPU使用率可能會(huì)需要3.25—3.5倍的時(shí)長(zhǎng)來(lái)完成。我的經(jīng)驗(yàn)是,每個(gè)核都有多個(gè)線程試圖占用100%的CPU,但它們都不能達(dá)到目標(biāo)。
所以,要怎樣分配正在運(yùn)行的線程數(shù)量呢?
有一個(gè)辦法是在線程之間建立一個(gè)共享的旗語(yǔ)對(duì)象。在線程開(kāi)始運(yùn)行前,它會(huì)嘗試調(diào)用旗語(yǔ)的WaitOne模式,并在完成后釋放旗語(yǔ)。對(duì)CPU的核數(shù)量設(shè)置旗語(yǔ)限制,(使用EnvironmentProcessorCount功能限定);這將防止您的系統(tǒng)在同一時(shí)間運(yùn)行的線程數(shù)多于核數(shù)量。與此同時(shí),從線程池中拉出線程將確保您不會(huì)在同一時(shí)間創(chuàng)建過(guò)多線程。如果一次創(chuàng)建線程過(guò)多,即使他們并沒(méi)運(yùn)行,那也是浪費(fèi)系統(tǒng)資源。因?yàn)槊總(gè)線程都要消耗資源。使用旗語(yǔ)的一般模式如下所示:
|
以下為引用的內(nèi)容: static Semaphore threadBlocker; static void Execute(object state) {threadBlocker.WaitOne(); //Do work threadBlocker.Release(); } static void RunThreads() {threadBlocker = new Semaphore(0, Environment.ProcessorCount); {ThreadPool.QueueUserWorkItem(new WaitCallback (Execute)); } } |
當(dāng)然還有其他一些辦法可以解決這一問(wèn)題。前一段時(shí)間我想要保持對(duì)象的一份清單。每個(gè)對(duì)象代表每個(gè)工人部件的完整狀態(tài)。執(zhí)行和完成時(shí),工人部件都會(huì)被填入數(shù)據(jù)。并且他會(huì)設(shè)置某個(gè)功能以指示任務(wù)完成。主線程將掃描對(duì)象清單,如果運(yùn)行的線程數(shù)量足夠少,就開(kāi)始運(yùn)行另一個(gè)。說(shuō)實(shí)話,雖然這個(gè)方法可行,但對(duì)于代碼和調(diào)試來(lái)說(shuō)這絕對(duì)是個(gè)噩夢(mèng),所以我一點(diǎn)也不推薦。
數(shù)據(jù)完整性
總體而言,在數(shù)據(jù)完整性方面,你要擔(dān)心的問(wèn)題是競(jìng)爭(zhēng)條件和死鎖。多個(gè)線程試圖在同一時(shí)間更新相同的對(duì)象就會(huì)造成競(jìng)爭(zhēng)條件,這將招致麻煩。想象一下如果使用下面這段代碼:
|
以下為引用的內(nèi)容: int x=5; x=x 10; |
現(xiàn)在,如果線程A和線程B在同一時(shí)間運(yùn)行此代碼,將會(huì)發(fā)生什么情況?它可以運(yùn)行得很好?還是會(huì)出現(xiàn)什么問(wèn)題?如果出現(xiàn)問(wèn)題,又是些怎樣的問(wèn)題呢?每個(gè)線程都不會(huì)一次執(zhí)行全部語(yǔ)句。因此,我們可以按照以下順序操作:
|
以下為引用的內(nèi)容: 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架構(gòu)中,最簡(jiǎn)單也最常見(jiàn)的解決競(jìng)爭(zhēng)條件的方法是使用“臨界區(qū)”。而在VB.NET中,該語(yǔ)句是“加鎖”,并在C#中是“鎖定”,這兩種語(yǔ)句都是把對(duì)象作為參數(shù)。其他嘗試鎖定相同對(duì)象實(shí)例使用的臨界區(qū)(包括上文所指的)會(huì)阻止運(yùn)行直到鎖定解除,這樣每次就只有一個(gè)臨界區(qū)運(yùn)行。我們先前舉例的一段代碼現(xiàn)在看起來(lái)是這樣的:
|
以下為引用的內(nèi)容: int x=5; object lockObject=new object(); Monitor.Enter(lockObject); x=x 10; Monitor.Exit(lockObject); |
什么是監(jiān)控器可以提供而臨界區(qū)做不到的呢?答案是沒(méi)有。除非你在解鎖后需要更細(xì)粒度的控制權(quán)。有些復(fù)雜的代碼可能需要鎖定或長(zhǎng)或短的一段時(shí)間,這都取決于運(yùn)行的情況,比方一個(gè)變量的值。在這種情況下,選擇監(jiān)控器要比需選擇臨界區(qū)更合適。
另一個(gè)值得關(guān)注的有關(guān)數(shù)據(jù)完整性的問(wèn)題是死鎖。當(dāng)多個(gè)線程鎖定資源導(dǎo)致它們都不能夠繼續(xù)運(yùn)行時(shí),就會(huì)出現(xiàn)死鎖。例如:
|
以下為引用的內(nèi)容: 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都調(diào)用它們的第一段語(yǔ)句并且同時(shí)完成運(yùn)行,那它們都無(wú)法調(diào)用它們的第二段語(yǔ)句——這就是一個(gè)死鎖。所以編寫(xiě)代碼的時(shí)候細(xì)心,要仔細(xì)想清楚怎樣編寫(xiě)代碼才更有利。死鎖的發(fā)生常見(jiàn)于新手,因?yàn)樗麄冞^(guò)分設(shè)置鎖定把它變得太詳細(xì)了。如果代碼被嵌套鎖定通常表明需要對(duì)編寫(xiě)的代碼加以認(rèn)真檢查。
分享:淺析asp.net 里 include UTF8 垃圾問(wèn)題暫且不討論為什么要用 SSI,而不用其它技術(shù)(如 UserControl) 生成 index.shtml 肯定要帶 BOM,其實(shí)帶不帶也不會(huì)影響頁(yè)面上會(huì)出現(xiàn)空白行。 index.shtml 內(nèi)容如下: html body !--#include file=head.shtml-- /body /html 1、head.shtml 保存為 UTF-8 帶 BOM
- asp.net如何得到GRIDVIEW中某行某列值的方法
- .net SMTP發(fā)送Email實(shí)例(可帶附件)
- js實(shí)現(xiàn)廣告漂浮效果的小例子
- asp.net Repeater 數(shù)據(jù)綁定的具體實(shí)現(xiàn)
- Asp.Net 無(wú)刷新文件上傳并顯示進(jìn)度條的實(shí)現(xiàn)方法及思路
- Asp.net獲取客戶端IP常見(jiàn)代碼存在的偽造IP問(wèn)題探討
- VS2010 水晶報(bào)表的使用方法
- ASP.NET中操作SQL數(shù)據(jù)庫(kù)(連接字符串的配置及獲取)
- asp.net頁(yè)面?zhèn)髦禍y(cè)試實(shí)例代碼
- DataGridView - DataGridViewCheckBoxCell的使用介紹
- asp.net中javascript的引用(直接引入和間接引入)
- 三層+存儲(chǔ)過(guò)程實(shí)現(xiàn)分頁(yè)示例代碼
.Net教程Rss訂閱編程教程搜索
.Net教程推薦
- 帶你走進(jìn)ASP.NET(2)
- 基于自定義Unity生存期模型PerCallContextLifeTimeManager的問(wèn)題
- 使用ASP.NET開(kāi)發(fā)移動(dòng)通訊的幾種方法
- .NET:InTheHand提供的類操作SMS
- 在asp.net 2.0 中使用的存儲(chǔ)過(guò)程解析
- 淺談ASP.NET的PHP執(zhí)行速度
- 進(jìn)程性能計(jì)數(shù)器已禁用的解決辦法
- 解讀ASP.NET密碼強(qiáng)度驗(yàn)證代碼實(shí)例
- AjaxPro讓.NET的AjaxPro變得簡(jiǎn)單
- 關(guān)于利用C#遠(yuǎn)程存取Access數(shù)據(jù)庫(kù)
- 相關(guān)鏈接:
- 教程說(shuō)明:
.Net教程-分析.NET上執(zhí)行多線程應(yīng)該注意的兩點(diǎn)
。