![VisualStudio2010中調(diào)試基于任務(wù)_第1頁](http://file1.renrendoc.com/fileroot_temp2/2020-10/1/40d1deb2-afc4-46ce-b1e6-e694a8cbf903/40d1deb2-afc4-46ce-b1e6-e694a8cbf9031.gif)
![VisualStudio2010中調(diào)試基于任務(wù)_第2頁](http://file1.renrendoc.com/fileroot_temp2/2020-10/1/40d1deb2-afc4-46ce-b1e6-e694a8cbf903/40d1deb2-afc4-46ce-b1e6-e694a8cbf9032.gif)
![VisualStudio2010中調(diào)試基于任務(wù)_第3頁](http://file1.renrendoc.com/fileroot_temp2/2020-10/1/40d1deb2-afc4-46ce-b1e6-e694a8cbf903/40d1deb2-afc4-46ce-b1e6-e694a8cbf9033.gif)
![VisualStudio2010中調(diào)試基于任務(wù)_第4頁](http://file1.renrendoc.com/fileroot_temp2/2020-10/1/40d1deb2-afc4-46ce-b1e6-e694a8cbf903/40d1deb2-afc4-46ce-b1e6-e694a8cbf9034.gif)
![VisualStudio2010中調(diào)試基于任務(wù)_第5頁](http://file1.renrendoc.com/fileroot_temp2/2020-10/1/40d1deb2-afc4-46ce-b1e6-e694a8cbf903/40d1deb2-afc4-46ce-b1e6-e694a8cbf9035.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、Visual Studio 2010 中調(diào)試基于任務(wù)本文來自MSDN雜志Daniel Moth和Stephen Toub下載示例代碼如果您詢問任何一個(gè)CPU或GPU硬件廠商,他們都會(huì)告訴您未來屬于眾核技術(shù)時(shí)代。處理器內(nèi)核的速度不會(huì)像過去四十年那樣以指數(shù)速度增長,而新的計(jì)算機(jī)會(huì)配備更多內(nèi)核。因此,應(yīng)用程序開發(fā)人員過去年復(fù)一年所依賴的免費(fèi)性能改進(jìn)將不復(fù)存在。為了重新獲得由越來越好的硬件所提供的免費(fèi)午餐,并通過新的對(duì)性能敏感的特性來增強(qiáng)應(yīng)用程序性能,您需要借助并行性來發(fā)揮多內(nèi)核的優(yōu)勢(shì)。在Visual Studio 2010所提供的Visual C+10和Microsoft.NET Framework
2、 4中,Microsoft將引入新的庫和運(yùn)行時(shí),從而顯著簡化在基本代碼中表達(dá)并行性的過程,同時(shí)還支持使用新工具對(duì)并行應(yīng)用程序進(jìn)行性能分析和調(diào)試。在本文中,您將了解Visual Studio 2010中的調(diào)試支持,其中很多內(nèi)容都以基于任務(wù)的編程模型為中心進(jìn)行講述?;谌蝿?wù)編程的需要將并行性融入應(yīng)用程序是為了利用多個(gè)內(nèi)核。單一的順序工作一次僅在一個(gè)內(nèi)核上運(yùn)行。要使應(yīng)用程序使用多個(gè)內(nèi)核,需要讓多項(xiàng)工作啟用多個(gè)線程,以便對(duì)該工作進(jìn)行并行處理。這樣,假如只有一項(xiàng)工作,那么要想通過多核執(zhí)行實(shí)現(xiàn)并行加速,就需要將該單一工作劃分為可并發(fā)運(yùn)行的多個(gè)單元。最簡單的方案是靜態(tài)劃分:將工作劃分為固定數(shù)目、固定大小的單
3、元。您當(dāng)然不想針對(duì)執(zhí)行該工作的每種硬件配置都編寫代碼,并且,隨著應(yīng)用程序在更大型和性能更佳的計(jì)算機(jī)上運(yùn)行,預(yù)先確定固定數(shù)目的單元將會(huì)抑制應(yīng)用程序的擴(kuò)展性。相反,您可根據(jù)計(jì)算機(jī)的具體情況,在運(yùn)行時(shí)動(dòng)態(tài)選擇單元數(shù)目。例如,您可按一個(gè)內(nèi)核處理一個(gè)單元對(duì)工作進(jìn)行劃分。這樣,如果所有單元所需的處理時(shí)間相等,并且每個(gè)單元使用一個(gè)線程,您就能夠使計(jì)算機(jī)滿負(fù)荷工作。但是,這種方法仍然差強(qiáng)人意。在實(shí)際環(huán)境中劃分工作負(fù)荷時(shí),很少能夠保證每個(gè)單元都占用同樣的處理時(shí)間,尤其在您將一些外部因素(如可能在計(jì)算機(jī)上同時(shí)運(yùn)行并消耗部分計(jì)算機(jī)資源的其他工作負(fù)荷)考慮在內(nèi)時(shí)。在這種情況下,每個(gè)內(nèi)核一個(gè)單元的劃分最終可能會(huì)造成不均
4、勻的工作分配:某些線程將先于其他線程完成其單元的處理,從而造成負(fù)荷不平衡,而某些內(nèi)核在其他內(nèi)核完成時(shí)處于空閑狀態(tài)。為解決這一問題,您需要對(duì)工作進(jìn)行深度劃分,將工作負(fù)荷劃分為可行的最小單元,以便計(jì)算機(jī)的所有資源都能參與工作負(fù)荷的處理,直到處理完成。如果執(zhí)行一個(gè)工作單元引起零開銷,則剛剛提出的解決方法將較為理想,但很少有實(shí)際環(huán)境中的操作會(huì)引起零開銷。根據(jù)過去的經(jīng)驗(yàn),線程一直是用于執(zhí)行這樣一個(gè)工作單元的機(jī)制:為每個(gè)工作單元?jiǎng)?chuàng)建一個(gè)線程,讓其執(zhí)行,然后終止該線程。遺憾的是,線程相對(duì)來說是重型的,以這種方式使用它們所產(chǎn)生的開銷可能會(huì)禁止我們所講的深度劃分類型。您所需要的是一種用于執(zhí)行這些已劃分的單元以將
5、開銷降到最低程度的更輕型機(jī)制-一種可使您更放心地進(jìn)行深度劃分的機(jī)制。通過這種方法,您不是為每個(gè)單元?jiǎng)?chuàng)建一個(gè)線程,而是利用一個(gè)計(jì)劃程序來計(jì)劃在它所管理的線程上執(zhí)行的各個(gè)單元,從而在保持單元數(shù)目盡可能少的同時(shí)仍能確保實(shí)現(xiàn)最大吞吐量。我們剛剛介紹的是一個(gè)線程池,它將線程管理成本在計(jì)劃給它的所有工作項(xiàng)中分?jǐn)偅瑥亩鴮⑴c單個(gè)工作項(xiàng)關(guān)聯(lián)的開銷降到最低。在Windows中,可通過從Kernel32.dll導(dǎo)出的QueueUserWorkItem函數(shù)訪問這種線程池。(Windows Vista還引入了新的線程池功能。)在.NET Framework 4中,可通過System.Threading.ThreadPo
6、ol類訪問這種線程池。雖然前面提到的API能以相對(duì)很小的開銷實(shí)現(xiàn)分解,但它們主要是針對(duì)即發(fā)即棄工作。例如,.NET Framework 4ThreadPool類沒有提供任何一致的機(jī)制用于異常處理、工作取消、等待工作完成、在工作完成時(shí)接收通知等等。這些差距是通過.NET Framework 4和Visual C+10中新的API來彌補(bǔ)的,這些新的API設(shè)計(jì)用于在托管代碼和本機(jī)代碼中進(jìn)行的基于任務(wù)的編程。任務(wù)代表這樣的工作單元:它們可由一個(gè)基礎(chǔ)計(jì)劃程序高效執(zhí)行,同時(shí)在使用和執(zhí)行控制方面仍提供豐富的功能。在Visual C+10中,這些API是以Concurrency:task_group和Conc
7、urrency:task_handle類型為中心的。在.NET Framework 4中,它們以新的System.Threading.Tasks.Task類為中心。圖1并行堆棧窗口圖2并行任務(wù)窗口Visual Studio當(dāng)前提供的調(diào)試方法軟件開發(fā)的歷史一再證明,編程模型在很大程度上獲益于示范調(diào)試支持,而Visual Studio 2010就提供了這樣的支持,它提供了兩個(gè)新的調(diào)試工具窗口,以幫助完成基于任務(wù)的并行編程。但在介紹這些新功能之前,我們先來回顧一下目前在Visual Studio中進(jìn)行調(diào)試的經(jīng)歷以作為鋪墊。(在本文的其余部分,我們將出于解釋目的而使用基于.NET任務(wù)的類型,但所介紹的
8、調(diào)試支持也同樣適用于本機(jī)代碼。)在Visual Studio中調(diào)試進(jìn)程的入口點(diǎn)當(dāng)然就是附加調(diào)試器。默認(rèn)情況下,當(dāng)您在Visual Studio中打開的一個(gè)項(xiàng)目中按F5(相當(dāng)于選擇調(diào)試啟動(dòng)調(diào)試命令)時(shí),就會(huì)發(fā)生調(diào)試器的附加。通過選擇調(diào)試附加到進(jìn)程菜單命令,您還可以手動(dòng)將調(diào)試器附加到一個(gè)進(jìn)程。附加調(diào)試器之后,下一步是進(jìn)入調(diào)試器。進(jìn)入調(diào)試器可通過多種方式發(fā)生,包括遇到一個(gè)用戶定義斷點(diǎn)、手動(dòng)中斷(通過調(diào)試全部中斷命令)、通過請(qǐng)求它的進(jìn)程(例如,在托管代碼中,通過對(duì)System.Diagnostics.Debugger.Break方法的調(diào)用),或者甚至在引發(fā)異常時(shí)。圖3查找素?cái)?shù)static void M
9、ain(string args)var primes=from nin Enumerable.Range(1,10000000).AsParallel().AsOrdered().WithMergeOptions(ParallelMergeOptions.NotBuffered)where IsPrime(n)select n;foreach(var prime in primes)Console.Write(prime+,);public static bool IsPrime(int numberToTest)/WARNING:Buggy!/2 is aweird prime:its ev
10、en.Test for it explicitly.if(numberToTest=2)return true;/Anything thats less than 2or thats even is not primeif(numberToTest 2|(numberToTest&1)=0)return false;/Test all odd numbers less than the sqrt of the target number./If the target is divisible by any of them,its not prime./We dont test evens,be
11、cause if the target is divisible/by an even,the target is also even,which we already checked upperBound=(int)Math.Sqrt(numberToTest);for(int i=3;i upperBound;i+=2)if(numberToTest%i)=0)return false;/Its prime!return true;在進(jìn)程進(jìn)入調(diào)試器之后,應(yīng)用程序中的所有線程都將暫停:在您繼續(xù)執(zhí)行之前,沒有代碼在該點(diǎn)執(zhí)行(調(diào)試器自身使用的線程除外)。通過執(zhí)行中的這種暫停,您可
12、檢查該時(shí)刻應(yīng)用程序的狀態(tài)。當(dāng)檢查應(yīng)用程序狀態(tài)時(shí),您的頭腦中常常會(huì)有一個(gè)狀態(tài)畫面,并且,您可使用各種調(diào)試器窗口來發(fā)現(xiàn)預(yù)期與現(xiàn)實(shí)之間的差別。開發(fā)人員在Visual Studio中使用的主要調(diào)試窗口是線程窗口、調(diào)用堆棧窗口和變量窗口(局部變量、自動(dòng)變量、監(jiān)視)。線程窗口顯示進(jìn)程中所有線程的列表,它包含線程ID和線程優(yōu)先級(jí)以及當(dāng)前線程的指示(一個(gè)黃色箭頭)等信息。默認(rèn)情況下,當(dāng)前線程是在調(diào)試器進(jìn)入進(jìn)程中時(shí)正在執(zhí)行的線程。關(guān)于線程的最重要信息可能是調(diào)試器中斷它的執(zhí)行時(shí)其執(zhí)行位置,此信息通過位置列中的調(diào)用堆棧幀顯示。將光標(biāo)懸停在該列上可顯示出同等重要的調(diào)用堆棧-線程到達(dá)當(dāng)前位置之前正在執(zhí)行的系列或方法調(diào)用
13、。調(diào)用堆棧窗口顯示了當(dāng)前線程的調(diào)用堆棧,該窗口提供了有關(guān)該調(diào)用堆棧的更加豐富的信息,包括交互機(jī)會(huì)。若要在調(diào)用堆棧窗口中顯示另一個(gè)線程的調(diào)用堆棧,您必須通過在線程窗口中雙擊該線程以將其激活為當(dāng)前線程。當(dāng)前線程的執(zhí)行所使用的方法(位于調(diào)用堆棧的頂端)由一個(gè)黃色箭頭指示,稱為最頂端幀、葉幀或活動(dòng)堆棧幀。這是您在離開調(diào)試器并繼續(xù)運(yùn)行應(yīng)用程序時(shí)線程繼續(xù)執(zhí)行所使用的方法。默認(rèn)情況下,活動(dòng)堆棧幀也是當(dāng)前堆棧幀。換言之,它是驅(qū)動(dòng)變量檢查的方法,我們將在下面對(duì)此進(jìn)行介紹。圖4設(shè)置條件斷點(diǎn)變量窗口用于檢查應(yīng)用程序中變量的值。本地方法的變量通常可在本地變量和自動(dòng)變量窗口中進(jìn)行瀏覽;全局狀態(tài)(未在方法中聲明的變量)可
14、通過添加到監(jiān)視窗口中進(jìn)行檢查。從Visual Studio 2005開始,越來越多的開發(fā)人員在檢查狀態(tài)時(shí)都會(huì)選擇將鼠標(biāo)指針懸停在有關(guān)變量上,然后查看得到的彈出數(shù)據(jù)提示(可將其視為快速監(jiān)視窗口的快捷方式)。務(wù)必注意,只有在變量處于當(dāng)前堆棧幀的范圍內(nèi)時(shí)才可顯示變量的值(如前所述,當(dāng)前堆棧幀默認(rèn)為當(dāng)前線程的活動(dòng)堆棧幀)。若要檢查線程調(diào)用堆棧中先前處于范圍中的變量,您需要通過在調(diào)用堆棧窗口中雙擊要檢查的堆棧幀來更改當(dāng)前堆棧幀。此時(shí),新的當(dāng)前堆棧幀由一個(gè)綠色彎尾箭頭指示(活動(dòng)堆棧幀保留黃色箭頭)。若還想檢查另一線程上的變量,您需要在線程窗口中更改當(dāng)前線程,然后在調(diào)用堆棧窗口中當(dāng)前線程的調(diào)用堆棧上切換當(dāng)前
15、幀。總之,當(dāng)您在調(diào)試器中進(jìn)入進(jìn)程時(shí),可非常輕松地檢查處于某個(gè)線程的執(zhí)行方法范圍內(nèi)的變量。但是,若要全面了解所有線程的執(zhí)行位置,您需要分別檢查每個(gè)線程的調(diào)用堆棧,為此需要雙擊每個(gè)線程以將其激活為當(dāng)前線程,并檢查調(diào)用堆棧窗口,然后才能在腦海中形成一個(gè)整體畫面。并且,若要檢查各個(gè)線程的各個(gè)堆棧幀上的變量,還需要兩個(gè)層次的間接尋址:切換線程,然后切換幀。并行堆棧當(dāng)應(yīng)用程序使用更多線程時(shí)(隨著人們使用具有更多處理資源的計(jì)算機(jī),這種情況將變得普遍),您需要能夠在單一視圖中看到這些線程在任意給定時(shí)刻的執(zhí)行位置。這就是Visual Studio 2010中的并行堆棧工具窗口所提供的功能。為了節(jié)約屏幕空間,同時(shí)
16、還要指示對(duì)并行方案特別重要的方法,對(duì)于在線程根處具有共同點(diǎn)的調(diào)用堆棧段,該窗口會(huì)將其合并到相同的節(jié)點(diǎn)中。例如,在圖1中,您可在單一視圖中看到三個(gè)線程的調(diào)用堆棧。該圖顯示了從Main到A再到B的一個(gè)線程,并顯示了從相同的外部代碼開始然后轉(zhuǎn)到A的另外兩個(gè)線程。其中的一個(gè)線程繼續(xù)轉(zhuǎn)到B,然后轉(zhuǎn)到某個(gè)外部代碼,另一個(gè)線程繼續(xù)轉(zhuǎn)到C,然后轉(zhuǎn)到某個(gè)AnonymousMethod。AnonymousMethod也是活動(dòng)堆棧幀,它屬于當(dāng)前線程。此窗口支持很多其他功能,如縮放、總覽視圖、通過標(biāo)記來過濾線程以及調(diào)用堆棧窗口中已提供的大多數(shù)功能。圖5選擇凍結(jié)此線程之外的全部線程命令圖6堆棧幀的合并如果您的應(yīng)用程序創(chuàng)
17、建的是任務(wù)而不是線程,則可以切換到以任務(wù)為中心的視圖。在此視圖中,將省略沒有執(zhí)行任務(wù)的線程的調(diào)用堆棧。另外,還將刪減線程的調(diào)用堆棧以表示任務(wù)的實(shí)際調(diào)用堆棧,也就是說,一個(gè)單線程調(diào)用堆棧可能包含兩個(gè)或三個(gè)您想分開并單獨(dú)查看的任務(wù)。通過并行堆棧窗口的一個(gè)特殊功能,您可將圖表固定在一個(gè)方法上,并清晰觀察該方法上下文的調(diào)用方和被調(diào)用方。圖7帶有依賴關(guān)系的基于任務(wù)的代碼static void Main(string args)/WARNING:Buggy!var task1a=Task.Factory.StartNew(Step1a);var task1b=Task.Factory.StartNew(S
18、tep1b);var task1c=Task.Factory.StartNew(Step1c);Task.WaitAll(task1a,task1b,task1c);var task2a=Task.Factory.StartNew(Step2a);var task2b=Task.Factory.StartNew(Step2b);var task2c=Task.Factory.StartNew(Step2c);Task.WaitAll(task1a,task1b,task1c);var task3a=Task.Factory.StartNew(Step3a);var task3b=Task.Fa
19、ctory.StartNew(Step3b);var task3c=Task.Factory.StartNew(Step3c);Task.WaitAll(task3a,task3b,task3c);并行任務(wù)除了可在并行堆棧窗口中查看任務(wù)的實(shí)際調(diào)用堆棧之外,另外一個(gè)新的調(diào)試器窗口還顯示了有關(guān)任務(wù)的其他信息,包括任務(wù)ID、分配給任務(wù)的線程、當(dāng)前位置以及創(chuàng)建時(shí)傳遞給任務(wù)的入口點(diǎn)(委托)。稱為并行任務(wù)窗口的這個(gè)窗口具有與線程窗口類似的功能,如指示當(dāng)前任務(wù)(運(yùn)行在當(dāng)前線程上的最頂端任務(wù))、能夠切換當(dāng)前任務(wù)、對(duì)任務(wù)進(jìn)行標(biāo)記以及凍結(jié)和解凍線程。圖8使用并行任務(wù)查找依賴關(guān)系問題狀態(tài)列對(duì)開發(fā)人員的價(jià)值或許是最大
20、的。通過狀態(tài)列中提供的信息,您可區(qū)分正在運(yùn)行的任務(wù)、正在等待的任務(wù)(位于另一個(gè)任務(wù)或同步基元上)以及發(fā)生死鎖的任務(wù)(等待任務(wù)的一種特殊形式,工具針對(duì)該任務(wù)檢測到循環(huán)等待鏈)。并行任務(wù)窗口還顯示計(jì)劃任務(wù),即尚未運(yùn)行但正處于某個(gè)隊(duì)列中等待由線程執(zhí)行的任務(wù)。圖2顯示了一個(gè)這樣的示例。并行任務(wù)和并行堆棧窗口上的詳細(xì)信息,請(qǐng)參閱博客張貼/Blog/labels/ParallelComputing.html和在/dd 554943(VS.100).aspx MSDN文檔。圖9死鎖代碼static void Main(string args)i
21、nt transfersCompleted=0;Watchdog.BreakIfRepeats()=transfersCompleted,500);BankAccount a=new BankAccountBalance=1000;BankAccount b=new BankAccountBalance=1000;while(true)Parallel.Invoke()=Transfer(a,b,100),()=Transfer(b,a,100);transfersCompleted+=2;class BankAccountpublic int Balance;static void Tran
22、sfer(BankAccount one,BankAccount two,int amount)lock(one)/WARNING:Buggy!lock(two)one.Balance-=amount;two.Balance+=amount;查找Bug了解新工具功能的最佳途徑就是在操作中觀察其行為。為此,我們創(chuàng)建了幾個(gè)包含Bug的代碼段,并將使用新工具窗口來查找代碼中的基本錯(cuò)誤。單步執(zhí)行首先考慮圖3中顯示的代碼。此代碼的目標(biāo)是輸出1和10,000,000之間的素?cái)?shù),并以并行方式進(jìn)行。(并行化支持由并行LINQ提供;有關(guān)更多信息,請(qǐng)參見/pfxteam and msd
23、/dd 460688(VS.100).aspx。)IsPrime的實(shí)現(xiàn)包含Bug,通過運(yùn)行該代碼并查看輸出的前幾個(gè)數(shù)字可以了解這一點(diǎn):2,3,5,7,9,11,13,15,17,19,23,25,.這些數(shù)字大多數(shù)為素?cái)?shù),但9、15和25不是。如果這是一個(gè)單線程應(yīng)用程序,您可能就很容易逐步檢查該代碼,以找出結(jié)果不準(zhǔn)確的原因。但是,當(dāng)在一個(gè)多線程程序中執(zhí)行單步執(zhí)行時(shí)(例如,選擇調(diào)試單步執(zhí)行),該程序中的任何線程都符合單步執(zhí)行的條件。這意味著隨著單步執(zhí)行的進(jìn)行,您可能會(huì)在線程之間跳轉(zhuǎn),這使得對(duì)控制流以及關(guān)于程序中當(dāng)前位置的診斷信息的理解更加困難。為了幫助解決這個(gè)問題,您
24、可利用調(diào)試器的幾個(gè)功能。第一個(gè)功能是設(shè)置條件斷點(diǎn)。如圖4所示,您可設(shè)置一個(gè)斷點(diǎn)(在本例中,斷點(diǎn)位于IsPrime方法的第一行上)并指示調(diào)試器僅在滿足特定條件時(shí)介入-在本例中,在計(jì)算出不準(zhǔn)確的素?cái)?shù)之一時(shí)介入。我們本可將調(diào)試器設(shè)置為在遇到這些值之一時(shí)介入(而不是遇到它們中的任何值時(shí)介入),但我們無法做出有關(guān)PLINQ將以什么順序在后臺(tái)計(jì)算值的假設(shè)。相反,我們告知調(diào)試器尋找這些值中的任何一個(gè)值,以便將它執(zhí)行中斷前的等待時(shí)間縮到最短。在調(diào)試器介入之后,我們想告知它僅單步執(zhí)行當(dāng)前線程。為此,我們可以利用調(diào)試器凍結(jié)和解凍線程的能力,并規(guī)定凍結(jié)的線程在解凍之前將不運(yùn)行。通過新的并行任務(wù)窗口,很容易找到應(yīng)允許
25、繼續(xù)執(zhí)行的線程(尋找黃色箭頭圖標(biāo))并凍結(jié)所有其他線程(通過上下文菜單),如圖5所示。將不相關(guān)的線程凍結(jié)之后,現(xiàn)在就可以單步執(zhí)行含有Bug的IsPrime。通過調(diào)試numberToTest=25,我們很容易看到存在的錯(cuò)誤:循環(huán)應(yīng)在其測試中包含upperBound值,而此值當(dāng)前被排除在外,原因是該循環(huán)使用小于運(yùn)算符而不是小于或等于運(yùn)算符。這里,25的平方根是5,25可被5整除,但將不對(duì)5進(jìn)行測試,這樣就錯(cuò)誤地將25歸為素?cái)?shù)。并行堆棧窗口還提供一個(gè)非常好的整合視圖,用于顯示在中斷時(shí)程序中所發(fā)生的事情。圖6顯示了應(yīng)用程序在再次運(yùn)行之后的當(dāng)前狀態(tài),這一次將使用調(diào)試器的全部中斷功能顯式介入。PLINQ正在
26、多個(gè)任務(wù)中執(zhí)行IsPrime,所有這些任務(wù)的numberToTest的值都可在彈出窗口中看到,此時(shí)顯示任務(wù)1正在處理numberToTest=8431901,而任務(wù)2正在處理numberToTest=8431607。依賴關(guān)系問題圖7中的代碼顯示了并行應(yīng)用程序中一個(gè)常見模式的實(shí)例。此代碼分出可能并行運(yùn)行的多個(gè)操作(step1a、step1b、step1c,它們都是窗體void StepXx()的方法),然后加入到其中。隨后,該應(yīng)用程序通過代碼再次分支,由于存在對(duì)操作的副作用(如將數(shù)據(jù)寫到某些共享數(shù)組中)的依賴關(guān)系,該代碼要求前面的操作已完成。遺憾的是,此代碼包含一個(gè)Bug,編寫它的開發(fā)人員將看到
27、第三組任務(wù)計(jì)算出一些不準(zhǔn)確的結(jié)果。這意味著,即使這位開發(fā)人員正在等待前面所有任務(wù)的完成,還是存在差錯(cuò),并非前面的所有計(jì)算都已實(shí)際完成其結(jié)果。為了調(diào)試該代碼,開發(fā)人員在最后的WaitAll調(diào)用上設(shè)置一個(gè)斷點(diǎn),然后使用并行任務(wù)窗口查看程序的當(dāng)前狀態(tài),如圖8所示。并行任務(wù)窗口明確顯示,即使已對(duì)Step 3的任務(wù)進(jìn)行計(jì)劃,Step2c的任務(wù)仍在運(yùn)行。對(duì)第二個(gè)Task.WaitAll調(diào)用的檢查揭示了原因:由于鍵入錯(cuò)誤,正在等待task1a、task1b和task1c,而沒有等待task2的相應(yīng)操作。死鎖圖9提供了一種死鎖情況的原型示例,這種死鎖是因沒有注意鎖定次序而發(fā)生的。主代碼在銀行帳戶間連續(xù)進(jìn)行資金
28、劃轉(zhuǎn)。Transfer方法具有線程安全性,以便可從多個(gè)線程同時(shí)對(duì)它進(jìn)行調(diào)用。這樣,它就會(huì)從內(nèi)部鎖定傳遞給它的BankAccount對(duì)象,為此只需先鎖定第一個(gè)對(duì)象,然后再鎖定第二個(gè)對(duì)象。遺憾的是,如此代碼運(yùn)行結(jié)果所示,這種行為可能會(huì)導(dǎo)致死鎖。最終,調(diào)試器在發(fā)現(xiàn)沒有劃轉(zhuǎn)繼續(xù)進(jìn)行時(shí)介入。(介入是使用代碼執(zhí)行的,該代碼若發(fā)現(xiàn)在一段特定時(shí)間之后沒有新的劃轉(zhuǎn)完成,就會(huì)發(fā)出Debugger.Break。此代碼包含在隨本文提供的代碼下載中。)圖10有關(guān)并行任務(wù)中死鎖的信息圖11顯示死鎖的并行堆棧圖12并行堆棧中的方法視圖當(dāng)您在調(diào)試器中工作時(shí),立即會(huì)看到一個(gè)表明存在死鎖的圖形表示,如圖10所示。該圖還顯示,在等
29、待死鎖狀態(tài)上懸停指針將提供有關(guān)正在等待的確切內(nèi)容以及哪個(gè)線程正在占據(jù)受保護(hù)資源的詳細(xì)信息。查看線程分配列,您會(huì)看到任務(wù)2正在等待由任務(wù)1占據(jù)的一個(gè)資源,如果您將指針懸停在任務(wù)1上,您將看到相反的情況。也可從并行堆棧工具窗口得知此信息。圖11顯示了并行堆棧中的任務(wù)視圖,它突出顯示出存在兩個(gè)任務(wù),每個(gè)任務(wù)都在對(duì)Monitor.Enter的一個(gè)調(diào)用中被阻止(因圖9中的lock語句)。圖12展示了并行堆棧窗口中的方法視圖(通過相應(yīng)工具欄按鈕訪問)。通過重點(diǎn)查看Transfer方法,很容易可以看到Transfer中目前有兩個(gè)任務(wù),它們都已轉(zhuǎn)到對(duì)Monitor.Enter的調(diào)用上。將指針懸停在該框上將提供有關(guān)兩個(gè)任務(wù)的死鎖狀態(tài)的詳細(xì)信息。圖13創(chuàng)建鎖保護(hù)static void Main(string args)/WARNING:Buggy!object obj=new object();Enumerable.Range(1,10).Select(i=v
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 環(huán)境管理在企業(yè)發(fā)展中的作用研究
- 生產(chǎn)流程優(yōu)化基于數(shù)據(jù)的決策支持方案
- 珠寶鑒定與法律法規(guī)關(guān)系解析
- 安保安全措施方案
- 2023九年級(jí)化學(xué)下冊(cè) 第九章 現(xiàn)在生活與化學(xué)9.4 化學(xué)物質(zhì)與健康第3課時(shí) 治病用的藥品、防范有害化學(xué)物質(zhì)、保護(hù)身體健康說課稿 科粵版
- Unit1 Making friends Part A Letters and sounds(說課稿)-2024-2025學(xué)年人教PEP版(2024)英語三年級(jí)上冊(cè)
- 3 學(xué)習(xí)有方法 說課稿-2024-2025學(xué)年道德與法治三年級(jí)上冊(cè)統(tǒng)編版
- Unit 3 Fascinating parks Discover Useful Structures 說課稿 -2024-2025學(xué)年高中英語人教版(2019)選擇性必修第一冊(cè)
- 《2 拉拉手交朋友》說課稿-2023-2024學(xué)年道德與法治一年級(jí)上冊(cè)統(tǒng)編版
- 2023六年級(jí)數(shù)學(xué)上冊(cè) 三 分?jǐn)?shù)除法 1分?jǐn)?shù)除法第1課時(shí) 倒數(shù)的認(rèn)識(shí)說課稿 西師大版
- 電力服務(wù)收費(fèi)標(biāo)準(zhǔn)附表
- 小學(xué)主題班會(huì)教學(xué)設(shè)計(jì)-《給你點(diǎn)個(gè)“贊”》通用版
- 【教學(xué)創(chuàng)新大賽】《系統(tǒng)解剖學(xué)》教學(xué)創(chuàng)新成果報(bào)告
- 賽意EAM設(shè)備管理IOT解決方案
- 氫氰酸安全技術(shù)說明書MSDS
- 動(dòng)物檢疫技術(shù)-動(dòng)物檢疫的范圍(動(dòng)物防疫與檢疫技術(shù))
- 比較思想政治教育學(xué)
- 醫(yī)用內(nèi)窺鏡冷光源產(chǎn)品技術(shù)要求深圳邁瑞
- 砌墻磚和砌塊檢測作業(yè)指導(dǎo)書
- 護(hù)理教學(xué)查房評(píng)分標(biāo)準(zhǔn)
- GB/T 23505-2017石油天然氣工業(yè)鉆機(jī)和修井機(jī)
評(píng)論
0/150
提交評(píng)論