寫在前面
最近在弄一個傳輸組件,用到很多多線程的知識,其中有個問題,困擾我很久,不知道是什么原因,腦子一熱,在傳輸過程中,添加了一句代碼Thread.Sleep(0)。那個問題竟然解決了,耗費我一上午的時間,一點一點的排查是不是代碼邏輯有問題。到最后一句話解決了,興奮歸興奮,但是為什么這句話就能解決我的問題呢?而且還是睡個0,是不是你也遇到過這種情況?不妨一起討論下這句神奇的代碼!
Thread.Sleep(0)妙解
這里收集了網上的一篇文章,解釋的非常有趣,轉載在博客中,也推薦給大家一起看看。
[轉載]Thread.Sleep(0)妙用
摘錄文章的幾段話,你也可以有個大概的概念。
操作系統中,CPU競爭有很多種策略。Unix系統使用的是時間片算法,而Windows則屬於搶占式的。
- 在時間片算法中,所有的進程排成一個隊列。操作系統按照他們的順序,給每個進程分配一段時間,即該進程允許運行的時間。如果在 時間片結束時進程還在運行,則CPU將被剝奪並分配給另一個進程。如果進程在時間片結束前阻塞或結束,則CPU當即進行切換。調度程序所要做的就是維護一張就緒進程列表,當進程用完它的時間片后,它被移到隊列的末尾。
- 所謂搶占式操作系統,就是說如果一個進程得到了 CPU 時間,除非它自己放棄使用 CPU ,否則將完全霸占 CPU 。因此可以看出,在搶占式操作系統中,操作系統假設所有的進程都是“人品很好”的,會主動退出 CPU 。在搶占式操作系統中,假設有若干進程,操作系統會根據他們的優先級、飢餓時間(已經多長時間沒有使用過 CPU 了),給他們算出一 個總的優先級來。操作系統就會把 CPU 交給總優先級最高的這個進程。當進程執行完畢或者自己主動掛起后,操作系統就會重新計算一 次所有進程的總優先級,然后再挑一個優先級最高的把 CPU 控制權交給他。
一個例子
例子說明:在控制台中創建兩個線程,在線程中分別輸出0-100的數字,代碼如下:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Thread thchild = new Thread(new ParameterizedThreadStart(Run)); 6 thchild.Start("thread 1 開始"); 7 Thread thchild2 = new Thread(new ParameterizedThreadStart(Run)); 8 thchild2.Start("thread 2 開始"); 9 Console.Read(); 10 } 11 static void Run(object obj) 12 { 13 14 for (int i = 0; i < 100; i++) 15 { 16 Console.WriteLine(obj.ToString() + "\t" + i.ToString()); 17 //Thread.Sleep(0); 18 } 19 } 20 }
測試結果
加上Thead.Sleep(0)測試結果
通過上面兩張圖的簡單對比,有這樣一種現象
在沒有Thread.Sleep(0)的時候,Thread1和Thread2交換的頻率比較低,在使用了Thread.Sleep(0)的時候,Thread1和Thread2交換頻率明顯增高。
總結
關於Thread.Sleep(0)的詳細內容可參考上面轉載的那篇文章,覺得介紹的更詳細,也比較有趣。當然給的例子,也是一種猜測性質的,系統中跑了那么多的線程,是不是對這個測試結果有干擾,也未可知。也不知道該怎么測試更合適。如果您也遇到過這種情況,不妨留言,討論一下。