2017-06-06 25 views
1

有一個Channel 9 Video試圖解釋線程和任務之間的區別。我通常喜歡9頻道的視頻,因爲他們的技術準確性不錯,但從我的理解來看,這個視頻的一些關鍵聲明是錯誤的。任務與線程的Channel 9解釋是否正確?

下面是語句:

  1. @〜1:48至〜2:30:線程是在存儲器和時間昂貴。每個線程獲得1 MB的用戶模式堆棧。
  2. @〜2:30到2:37:創建線程也需要時間。分配數據結構並初始化它們的時間。
  3. @〜2:38到2:45:上下文切換也需要時間。
  4. @〜2:58至3:23和3:48至:任務使用多核系統[...]因此,當您計算時,您正在使用多個核心。
  5. @〜5:02至5:30:線程運行在單個內核上,上下文切換髮生很多。
  6. @〜5:40至5:51:線程有不同的執行方式。它們在多個內核上執行。如你在圖中看到的那樣,線程已經開銷了。

這裏是我的想法,我想證實或證僞:

  1. 調用堆棧的數量是可配置的。這樣,線程限制不是~1300,而是32位進程的最高限制爲12000。那些誰擁有可用的Sysinternals TestLimit的副本可以試試:

    D:\>testlimit -t -n 64  
    Testlimit v5.04 - test Windows limits 
    By Mark Russinovich - www.sysinternals.com 
    
    Creating threads with 64 KB stacks... 
    Created 12500 threads. Lasterror: 8 
    

    堆棧大小也被暴露在Thread Constructor for .NET

  2. 任務依靠線程作爲基礎。這些線程取自線程池,但是線程池的線程需要在可以使用之前創建。 AFAIK,Mark Russinovich在Windows Internals書中也解釋說,內核結構(_ETHREAD)保存在內存中以供重用。這最大限度地減少了分配的開銷並將其減少到初始化。

    我沒有找到我一直在尋找的確切地點,但在Windows內部6,第1部分它說417頁:

    [...]執行線程對象可能或不可能被釋放。

  3. 由於任務依賴線程作爲技術實現,因此在任何情況下都會發生上下文切換。

  4. 如果我有2個線程,它們也可以在不同的處理器上執行。恕我直言,這是它的全部想法。

  5. 這位演講者在討論單核心繫統上的線程問題。恕我直言,任務在這種情況下也幾乎沒有任何好處。見4.)

  6. 見4.和5。)

  7. 該幻燈片可能是正確的,但並未顯示實際原因。該幻燈片丟失導致上下文切換的〜15ms時間片。如果線程需要等待結果,則只能使用任務來減少開銷。

    在這種情況下,幻燈片的下半部分也是不正確的,因爲工作1的第一部分似乎是阻塞的,在這種情況下,工作2只能執行。當工作2完成時,可以完成繼續工作1的條件。只有在時間片內發生所有事情,任務纔有好處。

    在任何情況下,上下文切換也將隨任務一起發生,遲早。

我曾試圖確認我有這些問題的幫助理解上SO

上面似乎是7點個人的問題。我問他們都在同一個地方,因爲

  • 所有的根源在於一個視頻
  • 一些問題互相依賴
  • 它來查找信息在一個地方比繼SO規則的恕我直言更重要一次提出一個問題。

回答

1

注意:沒有觀看視頻,純粹是基於OP中的信息。

調用堆棧的數量是可配置的。

也許,但並不真正相關,除非我們進入非常嚴謹的細節。

對於.NET任務依賴於線程作爲基礎。這些線程從線程池獲取 ,但是,線程池 的線程需要在可以使用之前創建。

有點正確......雖然我們需要在抽象和實現之間保持一個非常明確的界限。任務可以使用.Net中的Threadpool執行更加正確。

任務表示代碼的獨立部分(通常)可以同時運行其他代碼的想法。線程是類似性質的操作系統實現。

因爲任務依賴於線程作爲技術實現,所以在任何情況下都會發生上下文切換。

不正確。儘管任務可以在線程上運行,並且可以發生上下文切換,但任務包含一個提供更多靈活性的抽象層。

例如,要在線程之間交換執行,上下文切換必須在硬件中發生。爲了在任務之間交換執行,不必發生這樣的硬件上下文切換。任務可以在不同的線程之間移動,進入休眠狀態並在沒有單個硬件上下文切換的情況下恢復。

如果我有2個線程,它們也可以在不同的 處理器上執行。恕我直言,這是它的全部想法。

正確。

演講者正在討論單個核心繫統上的線程。恕我直言,任務在這種情況下也幾乎沒有任何好處。

不正確。任務在單線程系統上運行良好,因爲它們只是一個抽象。此外,您可以在單個線程中運行多個任務,而無需任何硬件上下文切換,從而提高性能。


這裏的主要概念問題似乎是Task = Thread的思想。不是這種情況。任務是打破工作的概念性方式。線程是具有某些行爲特徵的類似想法的實現。雖然任務可以在封面(不一定)的線程上運行,但抽象允許它們以與硬件線程完全不同的方式運行。

+0

我根本不知道.net,但聽起來好像'Task'是你提交給_thread pool_的東西,是嗎?如果是這樣,線程池的重點是_re-use_ threads。正如你所說,線程是創建和銷燬昂貴的。一個不斷需要在後臺執行小作業的程序可以爲每個線程啓動一個新線程,並在作業完成時銷燬該線程,或者可以使用一些長壽命的後臺線程,並用「任務'對象通過一個隊列。後一種策略效率更高。 –

+0

@jameslarge任務*可以*運行在線程池(例如task.run執行此IIRC),但這只是他們行爲的一個方面。 Task.FromResult不使用線程池,但它仍然是一項任務。此外,可以在不使用任務庫/ API的情況下使用線程池。使用線程池來處理任務是一種常見而有效的策略,這是正確的。 – NPSF3000

+0

「任務可以使用.Net中的線程池執行更爲正確。」 - 我同意。如果它不使用線程池,則需要從頭創建一個新線程,它具有與通常線程相同的性能。 –