<p>Linux下Pthreads多线程编程需掌握四点:一、用pthread_create()创建线程,入口函数为void func(void),主线程须pthread_join()等待;二、用pthread_mutex_t互斥锁保护共享数据,注意加锁/解锁顺序与清理;三、用pthread_cond_t条件变量实现高效等待/通知,配合while循环检查条件;四、线程可通过返回、pthread_exit()或取消终止,需正确清理锁、条件变量等资源。</p>

Linux下用Pthreads创建和管理线程,核心是理解线程生命周期、同步机制与资源安全。不依赖C++或高级封装,纯C + POSIX标准即可完成可靠多线程编程。
一、基础线程创建与启动
调用 pthread_create() 启动新线程,需传入线程ID、属性(常为NULL)、入口函数地址及参数指针。入口函数必须声明为 void* func(void*) 形式,返回值用于线程退出状态。
常见写法示例:
- 定义线程函数:void* worker(void* arg) { int id = *(int*)arg; printf("Thread %d running\n", id); return NULL; }
- 创建线程:pthread_t tid; int idx = 5; pthread_create(&tid, NULL, worker, &idx);
- 主线程需用 pthread_join() 等待子线程结束,否则可能在子线程运行前就退出,导致资源未回收
二、线程同步:互斥锁防止数据竞争
多个线程访问共享变量(如全局计数器)时,必须加锁。Pthreads提供 pthread_mutex_t 类型,使用前需初始化(静态初始化用 PTHREAD_MUTEX_INITIALIZER,动态用 pthread_mutex_init())。
关键操作顺序不能错:
- 进入临界区前调用 pthread_mutex_lock()(阻塞直到获得锁)
- 操作完共享数据后立即调用 pthread_mutex_unlock()
- 线程退出前必须释放锁,否则其他线程永久阻塞;建议配合 pthread_cleanup_push/pop 做异常保护
三、线程间协作:条件变量实现等待/通知
仅靠互斥锁无法高效等待某条件成立(如“缓冲区非空”)。此时搭配 pthread_cond_t 使用:pthread_cond_wait() 会自动释放锁并挂起线程,被唤醒后重新获取锁再返回。
典型模式:
- 定义全局条件变量和互斥锁:pthread_cond_t cond = PTHREAD_COND_INITIALIZER; pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
- 等待方:pthread_mutex_lock(&mtx); while (condition_is_false) pthread_cond_wait(&cond, &mtx); /* 操作共享数据 */ pthread_mutex_unlock(&mtx);
- 通知方:pthread_mutex_lock(&mtx); set_condition_true(); pthread_cond_signal(&cond); pthread_mutex_unlock(&mtx);
四、线程终止与资源清理
线程可通过三种方式结束:自然返回、调用 pthread_exit()、被其他线程取消(pthread_cancel())。注意:
- return 从线程函数返回等价于 pthread_exit(),但不能用 exit(),否则整个进程退出
- 被取消的线程需设置取消状态(pthread_setcancelstate())和类型(延迟取消更安全),并注册清理函数处理已分配资源
- 所有动态创建的互斥锁、条件变量、线程特定数据(TSD)都应在退出前调用对应 destroy 函数(如 pthread_mutex_destroy())
实际项目中,避免过度创建线程,优先考虑线程池;调试时可用 pthread_self() 打印线程ID,结合 gdb 的 info threads 和 thread apply all bt 查看状态。不复杂但容易忽略细节。











