為了提高 CPU 的使用率,將某些需要耗時較多的任務或是大量 I/O 操作 (I/O處理速度很慢),採用多執行緒可以適當地提高程式的執行效率。
在介紹多執行緒之前,先來說明多執行緒的相關概念。
- 程式 (Program) : 指尚未被 Load 到記憶體的 Code
- 程序 (Process) : 指正在執行的程式,Operating System (OS) 會分配其所需要的資源,至少存在一個或多個執行緒,主要包含: Code, Data, Heap, Stack
Code (Text Section) 儲存程序執行的代碼Data 可分為 global variable 跟 static variableHeap 動態配置記憶體空間給變數或函式Stack 儲存暫時性的資料 (local variable, function)
- 執行緒 (Thread) : 指 OS 分配 CPU 進行運算的基本單位,存在於 Process中。一旦CPU開始執行程式,就會至少有一個Thread運作
- 多執行緒 (Multithreading) : 指將一個程序中的任務分配給不同的執行緒,各個執行緒平行運作,不互相影響,並且在同一個程序的執行緒共享記憶體 (shared memory)
❗ 不同的程序間沒辦法共享記憶體,若有需要互相通訊,唯有依賴特別的設計才能擁有共享記憶體
使用多執行緒有什麼優點跟缺點呢~~
🔹 優點:
1. 提高 CPU 的使用效率
2. 當一個執行緒必須停下來等待與服務器連接或是需要佔據長時間處理的程序,可以放在後台處理,其他執行緒還是可以繼續運作,可以提高處理效能
🔹 缺點:
1. 若有大量的執行緒,就會影響其效能,因為 OS 需要在它們之間做切換 (Context Switch)
2. 更多的執行緒需要更多的記憶體空間
3. 因為資料是多個執行緒共享的,因此有可能會發生 Race Condition 的狀況
- 上下文切換 (Context Switch) : 指當 CPU 要從一個執行緒切換至另一個執行緒時,需要先儲存當前執行緒的狀態,再讀回將要執行的執行緒狀態。在切換的過程中,需要花費一些時間
- Context Switch 的發生時機 : 因為一顆 CPU 同時只能處理一項程序,OS 就會利用時間輪轉的方式,讓使用者感覺這些程序都是同時運作。當CPU 認為某執行緒執行夠久的時候,就會發出一個中斷 (Interrupt) 訊號,切換至另一個執行緒去運作
- 競爭危害 (Race Condition) : 指當一個 Thread 修改動作執行到一半時被切換,而另一個 Thread 也正好執行修改同一個地方時,可能會導致記憶體洩漏 (memory leak)
- Race Condition 的發生時機 : 因為程序有時間排程的問題 (發生 Context Switch),在多個執行緒的情況下,當兩個 Thread 同時修改一個資料時,可能造成變數的值錯誤,形成不可預期的結果,便造成了 Race Condition, 解決 Race Condition 的方法就是使用 Critical Section
- 臨界區段 (Critical Section) : 指存取共享資源的程式碼區域,而這些共享資源不能被多個執行緒存取,也就是指這些要受保護的程式區段稱為 Critical Section。
❗ 當執行緒進入臨界區段時,必須使用一些同步機制在臨界區段的進入點與離開點實現,以確保這些執行緒的安全。
- 同步機制 (Synchronized)有以下幾種 : 互斥鎖 (Mutex), 訊號量 (Semaphore), 條件變數 (Condition Variable), 原子變數 (Atomic), 隊列 (Queue), 事件 (Event)
⚠ 但是當這些鎖定機制用得不好時,有可能會產生 Deadlock 的狀況,所以要特別注意使用
- 死結、死鎖 (Deadlock) : 當兩個以上的 Thread,都在互相等待雙方停止執行並釋放資源,造成循環等待的情況
一旦發生 Deadlock 時,一般沒有好的辦法可以處理,很多時候只能重啟,所以要盡量避免 Deadlock 的狀況發生 !
以下有介紹 Python 跟 C++ 的多執行緒用法~~