pthread
(POSIX Threads)是 Unix/Linux 系统中用于多线程编程的标准 API,定义在 <pthread.h>
头文件中。它允许程序在单个进程中创建和管理多个并发执行的线程,共享相同的内存空间。以下是核心概念和常用函数的总结:
核心概念
-
线程创建与终止
- 每个线程有独立的栈,但共享堆和全局变量。
- 主线程退出可能导致子线程终止,需用
pthread_join
或pthread_detach
管理生命周期。
-
线程同步
- 互斥锁(Mutex):防止多个线程同时访问共享资源。
- 条件变量(Condition Variable):允许线程等待特定条件满足。
- 信号量(Semaphore):控制资源访问数量(需包含
<semaphore.h>
)。
-
线程安全
- 确保函数或数据在并发环境中正确执行,避免竞态条件(Race Conditions)。
常用函数
1. 线程管理
-
创建线程:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
thread
:线程标识符。attr
:线程属性(NULL 表示默认)。start_routine
:线程入口函数。arg
:传递给入口函数的参数。
-
等待线程结束:
int pthread_join(pthread_t thread, void **retval);
- 阻塞调用线程,直到目标线程结束。
-
分离线程:
int pthread_detach(pthread_t thread);
- 线程终止后自动释放资源,不可再被
pthread_join
。
- 线程终止后自动释放资源,不可再被
2. 互斥锁(Mutex)
-
初始化/销毁:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 静态初始化 int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); int pthread_mutex_destroy(pthread_mutex_t *mutex);
-
加锁/解锁:
int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex);
3. 条件变量(Condition Variable)
-
初始化/销毁:
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; // 静态初始化 int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); int pthread_cond_destroy(pthread_cond_t *cond);
-
等待/通知:
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); int pthread_cond_signal(pthread_cond_t *cond); // 唤醒一个等待线程 int pthread_cond_broadcast(pthread_cond_t *cond); // 唤醒所有等待线程
示例代码
1. 创建线程并等待结束
#include <stdio.h>
#include <pthread.h>
void* print_message(void *msg) {
printf("%s\n", (char*)msg);
return NULL;
}
int main() {
pthread_t tid;
char *message = "Hello from thread!";
pthread_create(&tid, NULL, print_message, message);
pthread_join(tid, NULL); // 等待线程结束
return 0;
}
2. 使用互斥锁保护共享数据
#include <stdio.h>
#include <pthread.h>
int counter = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* increment_counter(void *arg) {
for (int i = 0; i < 100000; i++) {
pthread_mutex_lock(&mutex);
counter++;
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main() {
pthread_t t1, t2;
pthread_create(&t1, NULL, increment_counter, NULL);
pthread_create(&t2, NULL, increment_counter, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("Final counter: %d\n", counter); // 应为 200000
return 0;
}
编译与链接
使用 gcc
编译时需添加 -lpthread
选项:
gcc program.c -o program -lpthread
常见问题
-
竞态条件(Race Condition)
- 未正确同步线程导致数据不一致,需用互斥锁或原子操作。
-
死锁(Deadlock)
- 多个线程互相等待对方释放锁,需确保锁的顺序一致。
-
资源泄漏
- 忘记销毁互斥锁或条件变量,导致内存泄漏。
-
线程安全函数
- 避免使用非线程安全函数(如
strtok
),改用strtok_r
。
- 避免使用非线程安全函数(如
调试工具
- Valgrind:检测内存泄漏和竞态条件。
- gdb:支持多线程调试(
info threads
,thread <id>
)。 - Helgrind:专用于检测多线程问题。
掌握 pthread
是理解并发编程的基础,实际开发中也可考虑更高级的库(如 OpenMP)或语言特性(如 C++ 的 <thread>
)。