2014-10-10 25 views
3

這是一個相當普遍的計算機科學問題,並不針對任何操作系統或框架。線程池和上下文切換(任務)?

所以我有點困惑與線程池上切換任務相關的開銷。在許多情況下,爲每個作業提供自己的特定線程(我們不想創建太多硬件線程)是沒有意義的,所以我們把這些作業放到可以安排在線程上運行的任務中。我們建立了一個線程池,然後動態分配任務以在從線程池獲取的線程上運行。

對於在特定線程(在線程池中)切換任務相關的開銷,我只是有點困惑(無法找到深入的答案)。 DrDobbs的一篇文章(來源於下文)說明了它的作用,但我需要更深入地回答實際發生的事情(可以引用的來源會非常棒:))。

根據定義,SomeWork必須在池中排隊,然後在 上運行與原始線程不同的線程。這意味着我們必然 招致排隊開銷加上一個上下文切換隻是將工作移動到 池。如果我們需要將回答傳回原始線程(例如通過消息或Future或類似的),我們將爲此另外發送一個上下文切換。

來源:http://www.drdobbs.com/parallel/use-thread-pools-correctly-keep-tasks-sh/216500409?pgno=1

哪些組件的線程的實際切換?線程本身並不實際切換,只是特定於線程的數據。與此相關的開銷是多少(或多或少)?

回答

0

本文可能會討論將工作發佈到池中並等待其結果的情況。通常在線程池上運行任務不會導致任何上下文切換開銷。

想象一下排隊1000個工作項目。線程池線程將一個接一個地執行它們。所有這些之間沒有一個單獨的上下文切換。

切換髮生等待/阻塞。

+0

這開始變得更有意義(有點)。所以「線程池」線程並沒有實際的上下文切換。文章指出有一個上下文切換來排隊任務(即將任務移動到線程池)。你是說同樣的事情嗎?線程池不上下文切換,但任務呢?即將任務從創建任務的線程移動到將運行任務的線程 – smjpl 2014-10-10 18:34:50

+0

任務只是一個數據結構(一個函數指針)。隊列也只是數據。內核不參與排隊任務或執行它們。沒有開關。 – usr 2014-10-10 18:49:26

+0

那麼爲什麼我們需要確保任務足夠大,如果在線程池中排隊和運行任務沒有任何相關開銷?從文章(第1頁):「另一方面,任務不應該太短,因爲執行工作作爲線程池任務存在實際成本。」 – smjpl 2014-10-10 19:05:53

2

let's這裏澄清前5個關鍵概念,然後再討論他們在一個線程池的背景下如何關聯:

  • 螺紋: 在它可以被描述爲一個程序執行上下文簡短的簡歷,給通過正在運行的代碼,cpu註冊表和堆棧中的數據。當一個線程被創建時,它被分配了應該在該線程上下文中執行的代碼。在每個cpu週期中,線程都有一條指令來執行,cpu註冊表中的數據和堆棧處於給定狀態。

  • 任務: 表示工作單元。這是分配給要執行的線程的代碼。

  • 上下文切換(來自維基百科): 是存儲和恢復線程狀態(上下文)的過程,以便以後可以從同一點恢復執行。這使多個進程共享一個CPU,並且是多任務操作系統的基本特徵。正如上面所解釋的,正在執行的代碼,cpu註冊表和堆棧是什麼構成的。

上下文切換是什麼線程。一項任務僅代表一項可以分配給待執行線程的工作安寧。在給定的時刻,一個線程可以執行任務。

  • 線程池(維基百科): 在計算機編程,線程池就是創建多個線程來執行多項任務,這通常是組織在一個隊列中。

  • 線程池隊列: 任務放置在由池中的線程執行的位置。這種數據結構是內存共享的平衡,線程可能競爭隊列/出隊,可能導致高負載情況下的爭用。

表示線程池的使用場景:

  • 在你的程序(在主線程中運行最後),您創建一個任務,並安排其在線程池中執行。
  • 該任務在線程池隊列中排隊。
  • 當一個線程從池中執行時,它從池中取出一個任務並開始執行它。
  • 如果沒有空閒的cpu從池中執行線程,操作系統在某個時間點(取決於線程調度器策略和線程優先級)將阻止線程執行,上下文切換到其他線程。

操作系統可以在任何時候停止執行一個線程,切換到另一個線程的上下文,返回它繼續停止的地方。

當與CPU競爭的活動線程的數量增加時,上下文切換的開銷增加。因此,理想情況下,線程池會嘗試使用最少的必要線程來佔用機器中所有可用的cpus。

如果你的任務沒有在某個地方編寫代碼塊,那麼上下文切換會被最小化,因爲它不會使用比機器上可用的cpus更多的線程。

當然,如果你只有一個內核,你的主線程和線程池將競爭相同的CPU。