線程池是高併發服務器優化線程創建銷毀開銷的經典模式。本文剖析線程池設計動機、工作流程、適用場景,並給出生產級可用的C語言實現(基於pthread,約240行)。
單線程處理請求模型:
T_total = T_create + T_execute + T_destroy
高併發下,T_create與T_destroy佔比極高。線程池通過預創建固定/動態數量線程,複用線程執行任務,顯著降低系統開銷。
typedef struct task {
void *(*run)(void *arg); // 任務執行函數
void *arg; // 任務參數
struct task *next; // 隊列指針
} task_t;
typedef struct threadpool {
pthread_mutex_t lock; // 互斥鎖
pthread_cond_t cond; // 條件變量
task_t *first, *last; // 隊列頭尾
int counter; // 當前線程總數
int idle; // 空閒線程數
int max_threads; // 最大線程數
int quit; // 銷毀標誌
} threadpool_t;
threadpool_init初始化鎖、條件變量,設置計數器、上限、退出標誌。
threadpool_add_tasktask_t節點,入隊(尾插)。idle>0)→pthread_cond_signal喚醒一個。max_threads→pthread_create新線程執行thread_routine。thread_routinewhile (1) {
lock();
idle++;
while (queue_empty && !quit) {
timedwait(2秒); // 超時無任務則退出線程(縮容)
if (timeout) break;
}
idle--;
if (task = dequeue()) {
unlock(); // 釋放鎖執行任務,允許並發添加新任務
task->run(task->arg);
free(task);
lock();
}
if (quit && queue_empty) { counter--; if(counter==0) signal(); unlock(); break; }
if (timeout && queue_empty) { counter--; unlock(); break; }
unlock();
}
關鍵細節:執行任務前必須解鎖,否則任務執行期間無法添加新任務,並發度退化為串行。
threadpool_destroyquit=1,廣播喚醒所有等待線程。pthread_cond_wait等待counter歸零。#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <pthread.h>
// ... 前文結構體定義 ...
// 條件變量封裝(init/lock/unlock/wait/timedwait/signal/broadcast/destroy)
// 見原文完整實現
void *thread_routine(void *arg) { /* 見上文核心邏輯 */ }
void threadpool_init(threadpool_t *pool, int threads) { /* 初始化 */ }
void threadpool_add_task(threadpool_t *pool, void *(*run)(void*), void *arg) { /* 添加任務 */ }
void threadpool_destroy(threadpool_t *pool) { /* 銷毀 */ }
// 測試任務
void *mytask(void *arg) {
printf("thread 0x%x working on task %d\n", (int)pthread_self(), *(int*)arg);
sleep(1);
free(arg);
return NULL;
}
int main() {
threadpool_t pool;
threadpool_init(&pool, 3); // 最大3線程
for (int i = 0; i < 10; i++) {
int *arg = malloc(sizeof(int));
*arg = i;
threadpool_add_task(&pool, mytask, arg);
}
sleep(15); // 等待任務完成(生產環境用pthread_join或計數器同步)
threadpool_destroy(&pool);
return 0;
}
編譯運行:gcc main.c -o main -lpthread -lrt
pthread_attr_setstacksize控制棧大小。int狀態碼。完整項目託管於GitHub:https://github.com/your-repo/threadpool-c
線程池是併發編程基石,理解其鎖與條件變量的協作機制,對掌握高性能服務器架構至關重要。