8天玩轉並行開發——第七天 簡要分析任務與線程池


         其實說到上一篇,我們要說的task的知識也說的差不多了,這一篇我們開始站在理論上了解下“線程池”和“任務”之間的關系,不管是

說線程還是任務,我們都不可避免的要討論下線程池,然而在.net 4.0以后,線程池引擎考慮了未來的擴展性,已經充分利用多核微處理器

架構,只要在可能的情況下,我們應該盡量使用task,而不是線程池。

 

首先看一下task的結構

從圖中我們可以看出Task.Factory.StartNew()貌似等同於用ThreadPool.QueueUserWorkItem()創建,但是請注意,我是用TPL的形式

使用線程池,要知道task出現以后,一直標榜着以更少的工作量,更低的性能消耗來PK原始線程。

 

     這里簡要的分析下CLR線程池,其實線程池中有一個叫做“全局隊列”的概念,每一次我們使用QueueUserWorkItem的使用都會產生一個

“工作項”,然后“工作項”進入“全局隊列”進行排隊,最后線程池中的的工作線程以FIFO的形式取出,效果圖類似如下:

這里要值得一提的是,在.net 4.0之后“全局隊列”采用了無鎖算法,相比以前版本鎖定“全局隊列”帶來的性能瓶頸有了很大的改觀。那么任務

委托的線程池不光有“全局隊列”,而且每一個工作線程都有”局部隊列“,效果圖如下

我們的第一反應肯定就是“局部隊列“有什么好處,可以考慮這樣的情況,當我們new一個task的時候“工作項”就會進去”全局隊列”,如果我們的

task執行的非常快,那么“全局隊列“就會FIFO的非常頻繁,那么有什么辦法緩解呢?當我們的task在嵌套的場景下,“局部隊列”就要產生效果了,

比如我們一個task里面有3個task,那么這3個task就會存在於“局部隊列”中。

 1   class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             var task = Task.Factory.StartNew(() =>
 6             {
 7                 var task1 = Task.Factory.StartNew(Run1);
 8                 var task2 = Task.Factory.StartNew(Run2);
 9                 var task3 = Task.Factory.StartNew(Run3);
10 
11                 Task.WaitAll(new Task[] { task1, task2, task3 });
12             });
13 
14             Console.Read();
15         }
16 
17         public static void Run1() { Thread.Sleep(100000); }
18 
19         public static void Run2() { Thread.Sleep(100000); }
20 
21         public static void Run3() { Thread.Sleep(100000); }
22     }

從圖中可以看到,其實“局部隊列“起到了一個分流的作用,也叫做”任務內聯化“,”局部隊列“采用的是”LIFO"的形式,其實這樣的形式也是

為了提升性能之用,因為Run3送到“局部隊列”中時可能還存在CPU的高速緩存中,所以從“局部隊列”中取出來相對來說更快一點,最后的效

果就是Run3要理論上優先於Run2,Run1先執行。

     現在我們再來考慮這樣一種情況,比如有兩個人,一個人干完了分配給自己的所有活,而另一個人卻還有很多的活,從人情上說,閑的人應

該接手點忙的人的活,同樣,對應圖中“線程2“跑完了“局部隊列”中的所有任務,並且同時發現”全局隊列“中已經沒有可以跑的”任務“了,然而

“線程1”里面還有Run1,Run2,Run3,那么此時“線程2”采用“FIFO”的形式竊取“線程1”里面的任務。

    從上面種種情況我們看到,這些分流和負載都是普通ThreadPool.QueueUserWorkItem所不能辦到的,所以說在.net 4.0之后,我們

盡可能的使用TPL,拋棄ThreadPool。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM