有一個Channel 9 Video試圖解釋線程和任務之間的區別。我通常喜歡9頻道的視頻,因爲他們的技術準確性不錯,但從我的理解來看,這個視頻的一些關鍵聲明是錯誤的。任務與線程的Channel 9解釋是否正確?
下面是語句:
- @〜1:48至〜2:30:線程是在存儲器和時間昂貴。每個線程獲得1 MB的用戶模式堆棧。
- @〜2:30到2:37:創建線程也需要時間。分配數據結構並初始化它們的時間。
- @〜2:38到2:45:上下文切換也需要時間。
- @〜2:58至3:23和3:48至:任務使用多核系統[...]因此,當您計算時,您正在使用多個核心。
- @〜5:02至5:30:線程運行在單個內核上,上下文切換髮生很多。
- @〜5:40至5:51:線程有不同的執行方式。它們在多個內核上執行。如你在圖中看到的那樣,線程已經開銷了。
這裏是我的想法,我想證實或證僞:
調用堆棧的數量是可配置的。這樣,線程限制不是~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
任務依靠線程作爲基礎。這些線程取自線程池,但是線程池的線程需要在可以使用之前創建。 AFAIK,Mark Russinovich在Windows Internals書中也解釋說,內核結構(
_ETHREAD
)保存在內存中以供重用。這最大限度地減少了分配的開銷並將其減少到初始化。我沒有找到我一直在尋找的確切地點,但在Windows內部6,第1部分它說417頁:
[...]執行線程對象可能或不可能被釋放。
由於任務依賴線程作爲技術實現,因此在任何情況下都會發生上下文切換。
如果我有2個線程,它們也可以在不同的處理器上執行。恕我直言,這是它的全部想法。
這位演講者在討論單核心繫統上的線程問題。恕我直言,任務在這種情況下也幾乎沒有任何好處。見4.)
見4.和5。)
該幻燈片可能是正確的,但並未顯示實際原因。該幻燈片丟失導致上下文切換的〜15ms時間片。如果線程需要等待結果,則只能使用任務來減少開銷。
在這種情況下,幻燈片的下半部分也是不正確的,因爲工作1的第一部分似乎是阻塞的,在這種情況下,工作2只能執行。當工作2完成時,可以完成繼續工作1的條件。只有在時間片內發生所有事情,任務纔有好處。
在任何情況下,上下文切換也將隨任務一起發生,遲早。
我曾試圖確認我有這些問題的幫助理解上SO
上面似乎是7點個人的問題。我問他們都在同一個地方,因爲
- 所有的根源在於一個視頻
- 一些問題互相依賴
- 它來查找信息在一個地方比繼SO規則的恕我直言更重要一次提出一個問題。
我根本不知道.net,但聽起來好像'Task'是你提交給_thread pool_的東西,是嗎?如果是這樣,線程池的重點是_re-use_ threads。正如你所說,線程是創建和銷燬昂貴的。一個不斷需要在後臺執行小作業的程序可以爲每個線程啓動一個新線程,並在作業完成時銷燬該線程,或者可以使用一些長壽命的後臺線程,並用「任務'對象通過一個隊列。後一種策略效率更高。 –
@jameslarge任務*可以*運行在線程池(例如task.run執行此IIRC),但這只是他們行爲的一個方面。 Task.FromResult不使用線程池,但它仍然是一項任務。此外,可以在不使用任務庫/ API的情況下使用線程池。使用線程池來處理任務是一種常見而有效的策略,這是正確的。 – NPSF3000
「任務可以使用.Net中的線程池執行更爲正確。」 - 我同意。如果它不使用線程池,則需要從頭創建一個新線程,它具有與通常線程相同的性能。 –