此次咱們從底層把線程說清楚

  從業兩年半,零零散散學習和寫過了很多多線程的代碼,但對於線程的理解一直處於朦朦朧朧的狀態。對於線程的概念、模型、使用場景和使用方法愈來愈熟悉,但對於「線程究竟是什麼」這一問題愈來愈沒底,今天我將零散的點和概念彙集起來,從底層向上逐層來看一下線程究竟是什麼。  算法

  

  首先從cpu提及,咱們知道,cpu執行指令分爲三個階段:取指令階段、指令譯碼階段、指令執行階段。編程

  對於cpu來講,並不存在線程這一律念,cpu眼裏只有指令和數據。對於內存中的信息,哪些是指令哪些是數據徹底依靠cs寄存器和ip寄存器的指向來判斷。咱們有兩個程序(假設都是單線程且沒有交互),對於cpu來講它們只是內存中的兩塊區域的代碼,相互獨立沒有關係。cpu在執行A程序的代碼時即是在執行A任務,執行B程序的代碼時即是在執行B任務。若是它們是併發執行的,那麼對於cpu來講,即是一下子在執行任務A,一下子在執行任務B。也就是說在cpu眼中,線程是獨立的任務,線程的切換是cpu在交替的執行不一樣的任務。數據結構

  真正實現線程這一律念,並指引cpu在不一樣的任務間切換的是操做系統。爲了方便描述任務並以此爲依據對任務進行調度,操做系統爲任務維護了一個專用的數據結構TCB(Thread Control Block,線程控制塊)。說到TCB,咱們不得不按照時序來講一下PCB(Process Control block)。多線程

  在早期的操做系統實現中並不存在線程的概念,與之對應的是進程。也就是說當時的操做系統粗暴的將一個任務總體的描述爲一條執行線,操做系統以任務爲單位進行資源分配,並以任務爲單位進行運行調度。這樣分配的結果即是,每次進行運行調度即進程切換時,也要同時切換資源的權限,形成很是大的開銷。併發

  因而後來的操做系統將資源分配單位任務調度單位分離開來,也就是咱們如今所說的進程與線程。以進程爲單位分配系統資源,以線程爲單位進行任務調度。線程擁有所屬進程的全部系統資源,這樣cpu在同一進程的線程間切換時便沒必要同時切換資源的權限,同時一個進程也擁有了在進程內部併發甚至並行處理的能力(一個大任務有了並行或併發處理子任務的能力),大大提升了運行的效率。(與面向對象編程思路相似,在不符合單一職責原則時對任務這一對象進行了進一步的抽象,按職責進行分治。)學習

  回到原來的話題,讓咱們看看操做系統是如何使用PCB和TCB來描述進程和線程的,下面是百度百科中PCB的描述:spa

  

 

   咱們能夠看到,PCB中包含了資源分配信息和運行調度信息。其中:進程狀態、CPU排班法爲進行運行調度時的依據,CPU寄存器、程序計數器爲運行調度時保存和恢復現場的依據,存儲管理器、會計信息、輸入輸出狀態則是對進程擁有的資源的描述。
操作系統

  對於TCB來講,不一樣操做系統有着不一樣的實現,但大體都是僅包含了運行調度時所需的信息,如線程狀態、調度算法、CPU寄存器、PC計數器等。PCB與TCB的關係以下圖所示:線程

 

   操做系統經過上述兩個數據結構對任務進行了管理,而後不斷的以此爲依據來引導cpu在不一樣的任務間切換,咱們以時間片輪轉法爲例子看一下操做系統引導cpu的過程:3d

  cpu執行任務A------>任務A的時間片用完,OS發出時鐘中斷終止cpu的執行------->保存終止任務A前的任務現場(cpu寄存器、pc計數器等)--------->從全部有效的TCB中按特定算法算出下一個被執行的任務B---------->將B任務的現場恢復,開始執行B任務(cs:ip指向了B任務上次終止時執行到的指令,cpu從該處再次開始執行B任務)

  總結一下:

  1.進程和線程是操做系統層級對各個獨立任務的抽象。線程的切換是cpu在不一樣任務的指令間切換。

  2.操做系統對線程進行調度,引導cpu不間斷的執行不一樣任務的指令,以達到在不一樣任務間切換的效果。

  3.進程是資源分配的基本單位,線程是運行調度的基本單位。進程和線程的分離是對任務抽象的更加成熟的結果。

  隨着操做系統的發展,爲了提升運行效率人們對任務的抽象進一步細化,在線程中又剝離出了用戶線程與核心線程的概念,咱們留着下期再扯。

 

@Author 牛有肉,轉載請註明出處

相關文章
相關標籤/搜索