[CS] 進程與線程的概念整理(process and thread)
keywords: process
, thread
, concurrent
, parallel
此篇為各筆記之整理,非原創內容,資料來源可見下方連結與文後參考資料:
- Process vs Thread @ ByteByteGo
- 30-04 之應用層的運算加速 - 並行運算 @ 拿鐵派的馬克 Blog
- 30-08 之應用層的 I/O 優化 ( 維護性 ) - 協程 Coroutine @ 拿鐵派的馬克 Blog
- 30-09 之應用層的兩個池 - 進 ( 線 ) 程池與連線池 @ 拿鐵派的馬克 Blog
- Is Node.js Really Single-Threaded? @ Better Programming
- 進程、線程、協程,傻傻分得清楚! @ 莫力全 Kyle Mo
「當程式碼要執行時,編譯好的程式碼會送到 OS 去處理,OS 會將不同的事務分派到不同的記憶體空間(也就是 process 的 heap 和 stack 所在)、program counter、PID (process id ) 等等。
一個 process 至少有一個 thread,稱作 primary thread,而這個 primary thread 可以建立更多其他的 thread,當這個 primary thread 執行結束 後,這個 process 就會跟著結束,也就是說,process 是在記憶體中執行的程式」- Achieving concurrency in Go。
process(進程、程序、處理序、行程)
- 每個應用程式至少都是一個 process
- 對作業系統來說,它是資源分配的最小單位
- 『 上下文切換 ( context switch ) 』,它是由作業系統的核心 ( kernel ) 來處理這工作
- Each process has its own memory address space. One process cannot pollute the memory space of another process. This implies that if one process fails, the others keep functioning.
多進程(multi-processing)
- 指的是在單一作業系統中使用兩個以上的 CPU 處理器(processor)來在同一時間執行多個進程
- 邏輯 cpu = 物理 cpu 個數 X cpu 核數 ( 先別管超線程 )。然後有幾個邏輯 cpu 就代表『 同一個 』時間可以開幾條生產線來工作
thread(線程、執行緒)
- A process has at least one thread called the "main thread". Threads within a process share a memory address space. Using the shared memory space (heap) allows threads to communicate with one another.
- One malfunctioning thread could bring down the entire process.
- 對作業系統來說,它是最小的操作單位,也是 cpu 的最小執行單位,且它包含在 process 中。
- thread 是程式碼片段實際的執行者,它可以存取 process, OS resources 等等提供的記憶體。
- 在執行程式碼時,thread 會將變數保存在記憶體空間中,稱作
stack
。stack 會在程式 runtime 執行,通常有固定容量(1 - 2MB),但在 thread 中的 stack 只有它自己可以使用,並不能和其它 thread 共享(可以想成變數有 scope 的概念?) - heap 則是 process 中的另一個屬性,它可以被該 process 中的任何 thread 取用,也就是 heap 是共享的記憶體空間。
- 在執行程式碼時,thread 會將變數保存在記憶體空間中,稱作
- 作業系統可以分配 cpu 直接給 thread 來進行工作,然後在同一個 process 中的 thread 都可以共享 process 的記憶體空間
- process 是 OS 分配資源的最小單位,而 thread 則是作業系統能夠進行運算排程的最小單位,也就是說實際執行任務的並不是進程,而是進程中的線程。
- 一個進程有可能有多個線程,其中多個線程可以共用進程的系統資源,可以把進程比喻為一個工廠,線程則是工廠裡面的產線,負責任務的實際執行
多執行緒(multi-threading)
- 在一個 process 中可以有多個 thread 以 concurrently(並行)或 parallelism(平行)的方式運作
- 當一個 thread 有 memory leak 的情況產生時,它 可能會耗盡其它 thread 的資源,進而導致整個 process 停滯
- 由於 multi-threading 的情況下,不同 thead 會共用記憶體資源,因此它們彼此之間需要合作,在同一時間點只能有一個 thread 去存取某個資料,以特定順序的方式執行 multiple threads 稱作「scheduling」。
🔥 重點
- thread 和 process 很重要的差異是,同一 process 中的不同 thread 其記憶體資源是可以共享的。
- concurrently 並不是真的「同時」運作,而是透過在 context 間快速切換(context switching)來看起來同時,但實際上一次還是只做一個;parallel 才是真的「同時」處理多個事務。
coroutine(協程、協同程序)
- Even though context switching between threads is faster than between process, it is still excessively costly. Fibers or coroutines are hence mechanisms for this.
- 協程想要將異步非阻塞的 I/O 操作變成同步的
- 在 Nodejs 中使用的 async/await 就是協程
- 協程是相較於線程更小的執行單位,但它是純應用端的執行單位,作業系統並不知道它,它與線程一樣有自己的記憶體空間
- process 是作業系統的最小資源管理單位,thread 是作業系統的最小操作單位,coroutine 是一個比一個 thread 更小的操作單位,但是它是透過應用層被操作,而不是被作業系統所操作
- Coroutine 無法提升性能,只是讓原本非阻塞的操作能夠被同步執行
進(線)程池(process/thread pool)
- 進(線)程池:預先建立好,帶有一堆進程的隊列,有需要時就進去拿,而不用重新建立,以此增加效能並減少執行時的延遲。
- 之所以要開多個 process 或 thread 常是因為要「並行運算」或做 I/o 處理
- 透過進程池可以幫助我們管理 process,並減少建立和結束 process 的資源消耗
- 同一個時間下,一個進程只會被分配到一顆 CPU 工作,假設進程池設 4 個,但只有一個 CPU,那基本上同一時間內最多只會有一個進程在工作
連線池(connection pool)
- 連線池:建立一個隊列來存放許多的連線
- 連線池可以減少資源消耗和時間處理,並且保護連線池連線的對象
- i/o 處理目前主要有兩種模式
- 多進(線)程模式:每一個 i/o 都要開一個 thread,若 thread pool 大小設為 20,表示同一時間最多只能有 20 個 thread,也就是同一個時間最多只能發出 20 個請求,這時候即使連線池提供 100 的大小也用不到
- reactor 非阻塞 i/o 模式
mysql 是一個請求就會開一個 thread 來處理
參考資料
- 30-04 之應用層的運算加速 - 並行運算 @ 拿鐵派的馬克 Blog
- 30-08 之應用層的 I/O 優化 ( 維護性 ) - 協程 Coroutine @ 拿鐵派的馬克 Blog
- 30-09 之應用層的兩個池 - 進 ( 線 ) 程池與連線池 @ 拿鐵派的馬克 Blog
- Is Node.js Really Single-Threaded? @ Better Programming
- Achieving concurrency in Go @ RunGo
- 進程、線程、協程,傻傻分得清楚! @ 莫力全 Kyle Mo