何謂並發 (What Is Concurrency)
Overview Table
| 概念 | 重點 |
|---|---|
| 並發的定義 | 兩個或兩個以上的獨立活動同時發生 |
| 任務切換 (task switching) | 單核快速輪替任務,造成「並發的假象」 |
| 硬體並發 (hardware concurrency) | 多核/多處理器真正平行執行多個任務 |
| Context switch 成本 | 保存 CPU 狀態與指令指標、載入新任務、快取重填 → 延遲 |
| 並發的兩種方式 | 多行程(隔離、IPC 複雜且慢)vs 多執行緒(共享位址空間、開銷小) |
| 並發 vs 平行 | 平行注重效能;並發注重任務分離與回應性 |
何謂並發
並發 (concurrency):兩個或兩個以上的獨立活動同時發生。生活中隨處可見——一邊走路一邊說話、兩隻手同時做不同動作。
- 電腦系統中的並發:在單一系統裡同時執行多個獨立任務。
- 並發並非新事物:多工作業系統的任務切換、多處理器伺服器的平行計算早已存在。
- 並發近年更受關注的原因:多核處理器普及,帶來真正的平行能力。
電腦系統中的並發
單核機器某一時刻只能執行一個任務,但可在單位時間內對任務多次切換——「這個任務做一會,另一個任務再做一會」,稱為任務切換 (task switching)。切換太快使人無法察覺任務曾被暫時擱置,形成「並發的假象」。
多核機器(單晶片多核處理器或多處理器)可以真正平行執行多個任務,稱為硬體並發 (hardware concurrency)。
真正平行(雙核,每任務各佔一核):
Core 1: |A1|A2|A3|A4|A5|A6|A7|A8|A9|A10|
Core 2: |B1|B2|B3|B4|B5|B6|B7|B8|B9|B10|
任務切換(單核,▒ = context switch 開銷):
Core 1: |A1|▒|B1|▒|A2|▒|B2|▒|A3|▒|B3|…
Context switch(上下文切換)成本——每次任務切換,作業系統必須:
- 保存當前任務的 CPU 狀態與指令指標
- 計算要切換到哪個任務
- 將新任務重新載入處理器
- CPU 可能還要把新任務的指令與資料載入快取——期間 CPU 停止執行指令,造成額外延遲
- 硬體執行緒 (hardware threads) 的數量 = 硬體可真正並行執行的獨立任務數(有些處理器一個核心可執行多個執行緒)。
- 即使是硬體並發系統,任務數往往超過硬體可平行的上限(一台電腦常有成百上千個任務、含背景任務),因此任務切換與硬體並發總是並存。
Important
無論單核或多核、任務切換或硬體並發,C++ 標準庫提供的技術與類別都一體適用;但如何使用並發,很大程度上取決於可用的硬體並發能力。
Warning
圖示為「任務均分、排程規則」的理想情況;實際上任務分割不均與排程不規則會使切換行為更混亂。任務切換與真正平行在行為上仍有微妙差異(例如時序假設),不能完全等同視之。
並發的方式:多行程 vs 多執行緒
書中比喻:開發人員 = 執行緒,辦公室 = 行程。兩人各在獨立辦公室(多行程)互不干擾但溝通困難、成本高;兩人共用一間辦公室(多執行緒)溝通容易,但可能互相干擾、爭搶資源(「參考手冊哪去了?」)。
| 面向 | 多行程並發 | 多執行緒並發 |
|---|---|---|
| 結構 | 每個行程一個執行緒 | 單一行程內多個執行緒 |
| 通訊方式 | 行程間通訊 (IPC):訊號、socket、檔案、管線 (pipe) | 共享位址空間:全域變數、指標、參考與資料可直接傳遞 |
| 通訊成本 | 複雜且慢(作業系統保護行程,防止互改資料) | 低,但需自行確保各執行緒看到的資料一致 |
| 啟動/管理開銷 | 高:啟動行程費時、OS 需資源管理行程 | 低:執行緒如「輕量級行程」,OS 記錄工作量小 |
| 安全性 | OS 提供保護 + 高階通訊機制 → 較易寫出安全的並發程式 | 缺乏執行緒間資料保護 → 較易出錯 |
| 分散能力 | 可透過遠端連線在不同機器上執行行程 | 僅限單一機器的單一行程內 |
| 代表 | Erlang 以行程為並發基礎元件 | C++ 等主流語言偏好的方式 |
Warning
C++ 標準未對行程間通訊提供原生支援,多行程方案必須依賴平台相關 API。因此本書(與本 vault)只關注多執行緒並發——之後所稱「並發」均指多執行緒實作。
Tip
多行程並非一無是處:行程間有 OS 保護與較高階的通訊機制,且可跨機器部署(雖增加通訊成本,但設計良好時能提升平行可用性與效能)。
並發與平行的區別
兩個概念對多執行緒而言大部分重疊,差異在關注點:
- 平行 (parallelism):更注重效能——利用硬體同時執行多任務來提高資料處理速度時,談的是平行性。
- 並發 (concurrency):關注點在任務分離或任務回應性時,談的是並發性。
Exam/Test Patterns
| 情境/關鍵字 | 答案 |
|---|---|
| 「單核 CPU 也能同時跑多個程式?」 | 能,靠任務切換(並發的假象) |
| 「真正同時執行多個任務」 | 硬體並發(多核/多處理器) |
| 「任務切換時 OS 做什麼」 | 保存 CPU 狀態與指令指標 → 選擇並載入新任務 → 快取重填造成延遲 |
| 「可真正並行的任務數量由什麼決定」 | 硬體執行緒數量 |
| 「行程間通訊為何複雜又慢」 | OS 對行程施加保護,避免行程互改資料 |
| 「執行緒間共享資料為何要小心」 | 共享位址空間、缺乏資料保護,必須確保資料一致性 |
| 「C++ 標準支援 IPC 嗎」 | 不支援,需平台 API;C++ 標準只涵蓋多執行緒 |
| 「注重效能」vs「注重任務分離/回應」 | 平行 vs 並發 |
Related Notes
- 01-Concurrency-Fundamentals/02-Why-Use-Concurrency
- 01-Concurrency-Fundamentals/03-Cpp-Concurrency-Support-and-First-Program
- 01-Concurrency-Fundamentals/Practice-Concurrency-Fundamentals
- 02-Thread-Management/03-Thread-Count-and-Identification(查詢硬體並發數
hardware_concurrency()) - 08-Designing-Concurrent-Code/02-Factors-Affecting-Performance(過多執行緒與 context switch 對效能的影響)