跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
C 语言线程池
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
{{DISPLAYTITLE:C语言线程池}} '''C语言线程池'''是一种并发编程技术,用于管理和复用多个线程,以提高多线程应用程序的性能和资源利用率。它通过预先创建一组线程并维护一个任务队列,避免了频繁创建和销毁线程的开销。 == 概述 == 线程池的核心思想是“线程复用”。在传统多线程编程中,每次需要执行新任务时都会创建新线程,任务完成后线程被销毁。这种方式在高并发场景下会导致: * 频繁的线程创建/销毁开销 * 系统资源浪费 * 线程数量不可控 线程池通过以下组件解决这些问题: * '''固定数量的工作线程''':预先创建,长期存在 * '''任务队列''':存放待执行的任务 * '''任务调度机制''':将任务分配给空闲线程 == 线程池实现 == 以下是一个基本的C语言线程池实现(需要POSIX线程库支持): <syntaxhighlight lang="c"> #include <pthread.h> #include <stdlib.h> #include <stdio.h> #define THREAD_NUM 4 typedef struct Task { void (*function)(void*); void* arg; struct Task* next; } Task; typedef struct ThreadPool { pthread_t threads[THREAD_NUM]; Task* task_head; pthread_mutex_t mutex; pthread_cond_t cond; int shutdown; } ThreadPool; void* worker(void* arg) { ThreadPool* pool = (ThreadPool*)arg; while (1) { pthread_mutex_lock(&pool->mutex); while (pool->task_head == NULL && !pool->shutdown) { pthread_cond_wait(&pool->cond, &pool->mutex); } if (pool->shutdown) { pthread_mutex_unlock(&pool->mutex); pthread_exit(NULL); } Task* task = pool->task_head; pool->task_head = pool->task_head->next; pthread_mutex_unlock(&pool->mutex); task->function(task->arg); free(task); } return NULL; } ThreadPool* thread_pool_create() { ThreadPool* pool = (ThreadPool*)malloc(sizeof(ThreadPool)); pool->task_head = NULL; pool->shutdown = 0; pthread_mutex_init(&pool->mutex, NULL); pthread_cond_init(&pool->cond, NULL); for (int i = 0; i < THREAD_NUM; ++i) { pthread_create(&pool->threads[i], NULL, worker, pool); } return pool; } void thread_pool_add_task(ThreadPool* pool, void (*function)(void*), void* arg) { Task* task = (Task*)malloc(sizeof(Task)); task->function = function; task->arg = arg; task->next = NULL; pthread_mutex_lock(&pool->mutex); if (pool->task_head == NULL) { pool->task_head = task; } else { Task* current = pool->task_head; while (current->next != NULL) { current = current->next; } current->next = task; } pthread_cond_signal(&pool->cond); pthread_mutex_unlock(&pool->mutex); } void thread_pool_destroy(ThreadPool* pool) { pool->shutdown = 1; pthread_cond_broadcast(&pool->cond); for (int i = 0; i < THREAD_NUM; ++i) { pthread_join(pool->threads[i], NULL); } pthread_mutex_destroy(&pool->mutex); pthread_cond_destroy(&pool->cond); free(pool); } </syntaxhighlight> === 代码说明 === 1. '''ThreadPool结构体''':包含线程数组、任务队列头指针、互斥锁和条件变量 2. '''worker函数''':工作线程的主循环,从队列获取并执行任务 3. '''thread_pool_create''':初始化线程池并创建工作线程 4. '''thread_pool_add_task''':向线程池添加新任务 5. '''thread_pool_destroy''':安全关闭线程池 == 使用示例 == 以下示例展示如何使用上述线程池计算斐波那契数列: <syntaxhighlight lang="c"> void fibonacci(void* arg) { int n = *(int*)arg; if (n <= 1) { printf("fib(%d) = %d\n", n, n); return; } int a = 0, b = 1, c; for (int i = 2; i <= n; ++i) { c = a + b; a = b; b = c; } printf("fib(%d) = %d\n", n, b); } int main() { ThreadPool* pool = thread_pool_create(); int nums[] = {10, 20, 30, 40, 50}; for (int i = 0; i < 5; ++i) { int* arg = malloc(sizeof(int)); *arg = nums[i]; thread_pool_add_task(pool, fibonacci, arg); } sleep(1); // 等待任务完成 thread_pool_destroy(pool); return 0; } </syntaxhighlight> '''输出示例''': <pre> fib(10) = 55 fib(20) = 6765 fib(30) = 832040 fib(40) = 102334155 fib(50) = 12586269025 </pre> == 线程池架构 == 线程池的工作流程可以用以下mermaid图表示: <mermaid> graph TD A[主线程] -->|添加任务| B[任务队列] B --> C[工作线程1] B --> D[工作线程2] B --> E[工作线程...] C --> F[执行任务] D --> F E --> F </mermaid> == 数学建模 == 线程池的性能可以用排队论模型分析。设: * <math>\lambda</math>:任务到达率(任务/秒) * <math>\mu</math>:单个线程处理速率(任务/秒) * <math>c</math>:线程数量 系统利用率: <math>\rho = \frac{\lambda}{c\mu}</math> 当<math>\rho < 1</math>时系统稳定,平均任务等待时间: <math>W_q = \frac{\rho}{c\mu(1-\rho)}</math> == 实际应用场景 == 1. '''Web服务器''':处理并发HTTP请求 2. '''数据库连接池''':复用数据库连接 3. '''批量数据处理''':如图像处理、日志分析 4. '''游戏服务器''':处理玩家并行请求 == 高级主题 == === 动态线程池 === 可根据负载动态调整线程数量: * 核心线程数:常驻线程 * 最大线程数:允许扩展到的上限 * 空闲线程超时:回收多余线程 === 任务优先级 === 实现优先级队列,使高优先级任务先执行: <syntaxhighlight lang="c"> // 修改Task结构体 typedef struct Task { void (*function)(void*); void* arg; int priority; // 优先级字段 struct Task* next; } Task; </syntaxhighlight> === 负载均衡 === 使用工作窃取(Work Stealing)算法: * 每个线程维护自己的任务队列 * 空闲线程可以从其他线程队列“窃取”任务 == 最佳实践 == 1. '''合理设置线程数量''':通常为CPU核心数的1-2倍 2. '''避免任务阻塞''':长时间运行的任务应使用回调或异步IO 3. '''任务原子性''':确保任务可以独立执行 4. '''资源清理''':正确释放线程池和任务资源 == 常见问题 == '''Q:线程池大小如何确定?''' A:考虑: * CPU密集型任务:N<sub>cpu</sub>+1 * IO密集型任务:2*N<sub>cpu</sub> * 公式:N<sub>threads</sub> = N<sub>cpu</sub> * U<sub>cpu</sub> * (1 + W/C) 其中U<sub>cpu</sub>是目标CPU利用率,W/C是等待时间与计算时间比 '''Q:如何处理任务异常?''' A:建议: 1. 在任务函数内部捕获异常 2. 记录错误日志 3. 避免异常影响线程池运行 == 扩展阅读 == * POSIX线程(pthread)规范 * 生产者-消费者模式 * 无锁队列实现 * 现代C++中的线程池实现(如C++17的execution) [[Category:编程语言]] [[Category:C]] [[Category:C 语言多线程与并发]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)