針對 C 語言 POSIX 執行緒(pthread)的三個核心問題:共享資源鎖機制、全雙工通訊執行緒模型、參數傳遞策略,進行深度比較與工程實踐指導。
| 維度 | 雙執行緒 + Mutex | 單執行緒循環 (寫→讀) |
|---|---|---|
| 並行性 | 真並行 (多核可同時執行不同任務) | 偽並行 (序列化執行) |
| 回應性 | 寫入不阻塞讀取邏輯 (視鎖粒度) | 寫入耗時長時讀取延遲 |
| 複雜度 | 需處理死鎖、鎖競爭、條件變數 | 邏輯簡單、無同步風險 |
| 適用場景 | 高頻寫入、低延遲讀取、多核優化 | 低頻操作、嚴格時序、資源受限 |
關鍵差異:雙執行緒下,寫入執行緒持有鎖期間,讀取執行緒嘗試加鎖會**阻塞睡眠** (佔用 CPU 時間片切換);單執行緒則嚴格依序執行,無上下文切換開銷。若寫入極快、讀取極頻,單執行緒反而效率更高。
| 維度 | 雙執行緒 (收/發分離) | 單執行緒循環 (發→收) |
|---|---|---|
| 阻塞風險 | 發送阻塞不影響接收緩衝區處理 | 任一阻塞導致另一方無法處理,易丟包 |
| 資料完整性 | 接收緩衝區及時排空,防溢位覆蓋 | 高負載下接收緩衝區滿溢位 |
| 實作複雜度 | 需共享 socket fd、關閉協調 | 邏輯線性、易除錯 |
工程共識:生產級網路服務**幾乎全部採用收發分離執行緒** (或 I/O 多路復用 epoll/kqueue/IOCP),單執行緒輪詢僅適合教學、極簡裝置。
| 策略 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| 結構體指標 (void* arg) | 型別安全、封裝性好、可傳遞多參數、支援動態配置 | 需額外 malloc/free、稍繁瑣 | 正式專案、多參數、可重入設計 |
| 全域變數 | 簡單、無需傳遞、所有執行緒可見 | 耦合度高、難測試、命名空間汙染、非可重入 | 極簡示例、單例資源、舊代碼維護 |
typedef struct {
int socket_fd;
char *buffer;
size_t buf_size;
pthread_mutex_t *lock;
} ThreadArgs;
void *worker(void *arg) {
ThreadArgs *args = (ThreadArgs*)arg;
// 使用 args->socket_fd 等
return NULL;
}
int main() {
ThreadArgs *args = malloc(sizeof(ThreadArgs));
args->socket_fd = sockfd;
args->buffer = malloc(BUF_SIZE);
args->lock = &mutex;
pthread_t tid;
pthread_create(&tid, NULL, worker, args);
// 記得在執行緒結束後 free(args->buffer); free(args);
}
epoll/IOCP 事件驅動模型。pthread_join 或 pthread_detach,避免殭屍執行緒洩漏資源。理解機制差異,才能根據效能、複雜度、維護性做出正確架構決策。