YauTz's Blog

Backend Engineer
正在成長茁壯的問題解決工程師

0%

進程 (Process)、線程 (Thread)、協程 (Coroutine)

常常分不清楚進程 (Process)、線程 (Thread)、協程 (Coroutine)這三個有什麼差別嗎?
不了解這三者的到底有何關係嗎?

Process - 進程、程序

什麼是Process

Process指的就是執行中的程式實例,而一個Process會被分配到的OS資源有CPU Time、Memory、I/O Devices 等,簡單來說這個Process執行的時候會需要用到多久的 CPU 時間、花費多少記憶體、甚至可能會需要一些 I/O 設備的資源。

可以打開工作管理員來看看,一個應用程式就是對應一個Process,而Process對於作業系統(OS)來說也可以說是一個任務,每一個Process都會有各自對應的獨立地址空間。

為什麼要有Process

為了合理的壓榨CPU的效能和分配運行的資源,簡單來說不能讓CPU閒著

在電腦中,計算核心是CPU,負責所有計算相關的工作和資源,單個CPU一次只能執行一個任務,且一個Process執行時,就把唯一一個CPU給吃滿的話,那是蠻不合理的一件事,再加上CPU與RAM或其它硬體設備的運算速度相比是快上非常多的,所以才會去壓榨CPU。

Process主要組成

  1. Code Section(Text Section)
    指得是程式碼的部分, 每一個Process都是執行某一段程式碼所產生的

  2. Data Section
    指得是資料的部分, 代表Process所會用的資源(Ex: 全域變數、靜態變數)

  3. CPU Registers
    指的是CPU的暫存器的內容,專門暫存指令、資料和位址的記憶體空間

  4. Programming Counter & Other Registers
    指的是程式計數器,負責記錄下一個要執行程式的地址

  5. Stack
    包含Temporary data - 暫時性的資料
    Ex: Function Parameters、Local variables、return address

    補充 : 會稱作 stack 是由於其配置遵守 LIFO

  6. Heap
    包含Memory dynamically allocated during run time - 運行時的動態記憶體分配

    一般由程式設計師分配釋放,執行時才會知道配置大小
    Ex: malloc/new、free/delete、pointer變數

Process狀態

依據不同的情況會不同的狀態

  • new(新產生) : Process產生中
  • ready(就緒) : Process正在等待CPU分配資源,只要一拿到資源就可以馬上執行
  • running(執行中) : Process取得CPU資源並且執行中
  • waiting(等待) : Process在等待某個事件的發生,可能是等待 I/O 設備輸入輸出完成或是接收到一個信號,也可以想成是被 block (阻塞) 住
  • terminated(exit 完成) : Process執行完成,將資源釋放掉

記憶體足夠時的狀態轉換

  1. 建立好Process後
  2. 分配完Memory後進入ready
  3. 拿到CPU資源後進入running
  4. 中間會來回切換執行別的Process,執行完成之後就terminated
  5. 如果執行中間需要進行I/O或是意外狀況,則進入waiting等待例外事件完成

記憶體不足夠時的狀態轉換(swap-硬碟)

當記憶體不夠時,Process會先將本來要存入記憶體的資源會swap進硬碟中,等到有足夠的記憶體資源時,再從硬碟中取出,也因此導致Process的執行速度變慢

Context Switch

讓多個process可以分享單一個CPU資源的計算過程
當CPU Context Switch到另一個process,系統會儲存舊process的狀態並載入新process的狀態
Context switch 的時間是overhead,耗時根據硬體配備而不同

補充 : overhead就是執行一件任務的過程中,無用的開銷

交換的時機有以下幾種:

  • 多工
  • 中斷處理
  • 用戶態或者內核態的交換 (可能)

Process Control Block (PCB) : OS核心中一種資料結構,當切換process時,會把未做完的process相關資訊記錄在PCB裡

Process Scheduling Queue : OS在Process Scheduling Queue中維護所有的 PCB

  1. Job queue - 所有在系統上的Process
  2. Ready queue - 存在主記憶體中, 狀態為ready且準備執行的Process
  3. Device queues - 等待 I/O Device的Process

Schedule

Process輪換執行的機制, 有以下三種方式

  1. Long-Term Scheduler(或稱Job Scheduler)
    • Process狀態 new → ready
    • 從上述的job Queue中挑選合適的jobs,並載入到記憶體中準備執行
    • 通常適用於Batch System(大型機房),但不適用於Time-Sharing System(分時系統)
    • 執行頻率最
  2. Short-Term Scheduler(或稱CPU Scheduler)
    • Process狀態 ready → running
    • 從ready Queue中挑選高優先度的Process,使其獲得CPU控制權執行
    • Batch System和Time-Sharing均需要
    • 執行頻率最
  3. Medium-Term Scheduler
    • virtual memory
    • 當Memory空間不夠時,要把Process swap out到Disk中,直到空間足夠時再將Process swap in到Memory
    • 通常用在Time Sharing System

Process優缺

優點

  • 相對比較穩定安全,因為每一個Process都擁有獨立的OS資源,Process間較不容易互相影響,而且因為不會共享Data的問題,所以不須對Process作互斥存取之機制(互斥鎖)

缺點

  • 建立Process以及Process的上下文切換(Context Switch)都較消耗資源,Process間若有通訊的需求也較為複雜

Thread - 線程、執行緒

什麼是Thread

Thread又稱作是light weight process, 也就是輕量級的Process,Thread可以想像成是在Process裡面的,一個Process裡面至少會有一個Thread,而我們說Process會去執行任務,其實就是Process裡面的Thread去做的,所以沒有Process就沒有Thread。

當一個Process內有多個Thread,這些Thread會共享這個Process的OS資源,可以把Process比喻為一個工廠,Thread則是工廠裡面的工人,負責任務的實際執行。

為什麼要有Thread

  1. Process之間的資料難以共享,父子Process之間並未共享內存,需要通過IPC,在Process之間交換資料,效能開銷也比較大
  2. 建立Process(以fork的方式)的性能開銷比較大

Thread的主要組成

  • Thread ID
  • Programming Counter
  • CPU registers
  • stack

小結

  • Process是資源分配的最小單位,Thread是最小的操作單位,也是cpu的最小執行單位
  • 每個Process由一個Memory Space和一個以上的Thread所組成
  • 一個Process底下的所有Thread會共享資源
  • 同一個Process內的Thread使用相同的Memory Space, 但這些Thread各自擁有其Stack
    換句話說,Thread能透過reference存取到相同的Object,但是local variable各自獨立
  • OS會根據Thread的優先權以及使用過的CPU時間,在不同的Thread做切換,讓各個Thread都有執行的機會
  • Thread會有Race Condition資源競爭的問題

Multi-processing (多進程) & Multi-threading (多執行緒)

並發(Concurrent) vs 並行(Parallel)

  • Concurrent : 多個任務同時互相搶相同的CPU資源,搶到的就優先執行該任務,所以在一個時間點上只有一個任務在執行
  • Parallel : 每個CPU會各自負責自己的任務,而且是同事進行,沒有切換的問題

補充 : 單核心的電腦只能做到Concurrent,而現在的電腦都已經是多核心的才可以達到Parallel,也因為這樣現在電腦的速度相較以前快很多。

Multi-processing - 多進程

指多個Process在執行,彼此有各自的資料空間,若有資料需要共用,必須採用特別的方法(IPC)來傳遞,由於每個Process都需要一些資源來工作,所以Multi-processing會比Multi-threading更消耗資源。
補 : Google Chrome採用這種設計,因此會消耗不少記憶體

### Multi-threading - 多執行緒

指一個Process裡有多個Thread在執行,彼此共用相同的資料空間。

Multi-threading工作的其中一項特點就是隸屬在同一個Process下的所有Thread會分享該Process的所有資源,此外各Thread彼此間也可以擁有自己私有的資源而不與其它同一Process內的Thread共用。

Multi-processing vs Multi-threading

一間工廠(Process)擁有資源與設備但需要由員工(Thread)去操作才能生產產品。所以要做出一件成品,工廠內至少要有一位員工在做事。以電腦分時架構來看,不同的Process就像是不同的工廠,而Thread則像是一位派遣員工一樣由作業系統負責調度他在什麼時間該去那家工廠上班。

如果電腦擁有多個處理核心,即代表系統可以同時調用的員工數目增加,所謂人多好辦事,如此一來系統在為執行緒安排工作時就有兩種策略:

  1. 第一種策略是在同一時間內為各家工廠都分配一個員工去作事,這種方式稱作多行程(Multi-processing)平行執行。跟單一行程處理比起來,其優點在於可以在相同的時間內完成較多的工作
  2. 另一種策略是在同一時間內把所有員工都派到同一家工廠去工作,此法稱做多執行緒 (Multi-threading) 平行執行。相較於單一執行緒處理方式,它有機會讓相同的工作在比較短的時間內完成

Process & Thread的工廠例子

Coroutine

Coroutine是什麼

Coroutine是一種用戶態的輕量級Thread,可以想成一個Thread裡面可以有多個Coroutine,而Coroutine的調度完全由用戶控制,Coroutine也會有自己的資源,並且由Coroutine的調度器來控制說目前由哪個Coroutine執行,哪個Coroutine要被block住。

而相對於Process及Thread的調度,則是由CPU內核去進行調度,因此OS那邊其實會有所謂許多的調度算法,並且可以進行搶占式調度,可以主動搶奪執行的控制權。反之,Coroutine是不行的,只能進行非搶佔式的調度。可以理解成,如果Coroutine被block住,則會在用戶態直接切換另外一個 Coroutine給此Thread繼續執行,這樣其他Coroutine就不會被block住,讓資源能夠有效的被利用。

Coroutine優勢

  • 節省CPU : 避免系統內核集的Thread頻繁切換,造成CPU的資源浪費,再加上Coroutine是用戶態的線程,所以用戶可以自行控制Coroutine的建立與刪除,極大程度的避免了系統級Thread的資源切換
  • 節省內存 : 一個Thread需要花費幾MB的記憶體,而一個Coroutine只需要幾KB的記憶體
  • 稳定性 : 因為Thread之間會共享資源,如果當一個Thread出錯了,Process中的其他Thread也會有機率一起出錯
  • 開發效率 : 由於Coroutine可以給用戶控制,所以工程師可以做一些async的操作
    Ex : 讀寫文件、耗時的I/O請求

補充:用戶態vs內核態

參考資料

Go 面试官:什么是协程,协程和线程的区别和联系?
進程、線程、協程,傻傻分得清楚!
進程與線程的概念整理(process and thread
進程 (Process)、線程 (Thread)、協程 (Coroutine) 的概念講解
Process
OS - Ch3 行程 Process
【恐龍】理解 Process & Thread