目录
✅ 三、线程创建与等待:pthread_create 和 pthread_join
✅ 八、线程局部存储(Thread-Local Storage)
以下是 POSIX 线程(pthreads) 的 全面、系统、实战导向 的详解,适合从入门到掌握多线程编程。
✅ 一、什么是 POSIX 线程(pthreads)?
- POSIX:Portable Operating System Interface,一套 Unix/Linux 系统的标准。
- pthreads:POSIX Threads,定义了创建和操作线程的 API。
- 平台支持:Linux、macOS、FreeBSD 等类 Unix 系统原生支持。
- 头文件:
#include <pthread.h> - 链接库:编译时需加
-lpthread
gcc program.c -o program -lpthread
✅ 二、核心数据类型与函数
| 类型/函数 | 说明 |
|---|---|
pthread_t | 线程 ID 类型 |
pthread_create() | 创建线程 |
pthread_join() | 等待线程结束 |
pthread_detach() | 分离线程(自动回收资源) |
pthread_exit() | 线程主动退出 |
pthread_cancel() | 取消线程 |
pthread_mutex_t | 互斥锁类型 |
pthread_cond_t | 条件变量类型 |
✅ 三、线程创建与等待:pthread_create 和 pthread_join
🔧 函数原型
int pthread_create(
pthread_t *thread, // 输出:线程 ID
const pthread_attr_t *attr, // 属性(NULL 表示默认)
void *(*start_routine)(void *), // 线程函数
void *arg // 传给线程函数的参数
);
成功返回 0,失败返回错误码(非 errno)。
✅ 示例:创建并等待线程
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void *thread_func(void *arg)
{
int id = *(int *)arg;
printf("Thread %d is running...\n", id);
sleep(2);
printf("Thread %d exiting.\n", id);
return (void *)(long)(id * 100); // 返回值
}
int main()
{
pthread_t tid;
int thread_id = 1;
// 创建线程
if (pthread_create(&tid, NULL, thread_func, &thread_id) != 0)
{
perror("pthread_create failed");
return 1;
}
// 等待线程结束,并获取返回值
void *result;
pthread_join(tid, &result);
printf("Thread returned: %ld\n", (long)result);
printf("Main thread exiting.\n");
return 0;
}
输出:
Thread 1 is running...
Thread 1 exiting.
Thread returned: 100
Main thread exiting.
✅ 四、线程属性(pthread_attr_t)
用于设置线程的栈大小、分离状态、调度策略等。
示例:设置线程栈大小
pthread_attr_t attr;
pthread_t tid;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 1024 * 1024); // 1MB 栈
pthread_create(&tid, &attr, thread_func, NULL);
pthread_attr_destroy(&attr); // 释放属性对象
✅ 五、线程分离:pthread_detach
pthread_join:主线程等待,资源由主线程回收。pthread_detach:线程结束后自动释放资源,不能join。
// 方式1:创建后分离
pthread_detach(tid);
// 方式2:线程内部自分离
void *thread_func(void *arg)
{
pthread_detach(pthread_self());
// ... 工作
pthread_exit(NULL);
}
✅ 六、线程同步:互斥锁(Mutex)
防止多个线程同时访问共享数据。
🔧 基本操作
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 静态初始化
// 或动态初始化
// pthread_mutex_init(&mutex, NULL);
pthread_mutex_lock(&mutex); // 加锁
// 访问共享资源
pthread_mutex_unlock(&mutex); // 解锁
// 销毁
// pthread_mutex_destroy(&mutex);
✅ 示例:线程安全计数器
#include <stdio.h>
#include <pthread.h>
#define NUM_THREADS 10
#define LOOP_COUNT 100000
long long counter = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *increment(void *arg)
{
for (int i = 0; i < LOOP_COUNT; i++)
{
pthread_mutex_lock(&mutex);
counter++;
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main()
{
pthread_t threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++)
{
pthread_create(&threads[i], NULL, increment, NULL);
}
for (int i = 0; i < NUM_THREADS; i++)
{
pthread_join(threads[i], NULL);
}
printf("Expected: %d, Actual: %lld\n", NUM_THREADS * LOOP_COUNT, counter);
return 0;
}
✅ 七、条件变量(Condition Variables)
用于线程间通信,实现“等待-通知”机制。
🔧 常用函数
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_cond_wait(&cond, &mutex); // 等待条件
pthread_cond_signal(&cond); // 唤醒一个等待线程
pthread_cond_broadcast(&cond); // 唤醒所有等待线程
✅ 示例:生产者-消费者模型
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#define BUFFER_SIZE 5
int buffer[BUFFER_SIZE];
int count = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t not_full = PTHREAD_COND_INITIALIZER;
pthread_cond_t not_empty = PTHREAD_COND_INITIALIZER;
void *producer(void *arg)
{
for (int i = 0; i < 20; i++)
{
pthread_mutex_lock(&mutex);
while (count == BUFFER_SIZE)
{
printf("Buffer full, producer waiting...\n");
pthread_cond_wait(¬_full, &mutex);
}
buffer[count++] = i;
printf("Produced: %d, count = %d\n", i, count);
pthread_cond_signal(¬_empty);
pthread_mutex_unlock(&mutex);
sleep(1);
}
return NULL;
}
void *consumer(void *arg)
{
for (int i = 0; i < 20; i++)
{
pthread_mutex_lock(&mutex);
while (count == 0)
{
printf("Buffer empty, consumer waiting...\n");
pthread_cond_wait(¬_empty, &mutex);
}
int item = buffer[--count];
printf("Consumed: %d, count = %d\n", item, count);
pthread_cond_signal(¬_full);
pthread_mutex_unlock(&mutex);
sleep(2);
}
return NULL;
}
int main()
{
pthread_t prod, cons;
pthread_create(&prod, NULL, producer, NULL);
pthread_create(&cons, NULL, consumer, NULL);
pthread_join(prod, NULL);
pthread_join(cons, NULL);
return 0;
}
✅ 八、线程局部存储(Thread-Local Storage)
每个线程拥有独立的变量副本。
方式1:__thread(GCC 扩展)
__thread int thread_local_var = 0;
void *thread_func(void *arg)
{
thread_local_var = arg;
printf("Thread %d has value %d\n", (int)(long)arg, thread_local_var);
return NULL;
}
方式2:pthread_key_t(可移植)
pthread_key_t key;
void destructor(void *value)
{
free(value);
}
// 初始化
pthread_key_create(&key, destructor);
// 设置
int *val = malloc(sizeof(int));
*val = 100;
pthread_setspecific(key, val);
// 获取
int *my_val = pthread_getspecific(key);
✅ 九、线程取消与清理
取消线程
pthread_cancel(tid); // 请求取消线程
线程需设置取消状态和类型:
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
清理处理程序
void cleanup_handler(void *arg)
{
printf("Cleaning up: %s\n", (char *)arg);
}
void *thread_func(void *arg)
{
pthread_cleanup_push(cleanup_handler, "resource 1");
pthread_cleanup_push(cleanup_handler, "resource 2");
// 工作...
pthread_cleanup_pop(0); // 0: 不执行,1: 执行
pthread_cleanup_pop(0);
return NULL;
}
✅ 十、常见错误与最佳实践
| 问题 | 解决方案 |
|---|---|
| 数据竞争 | 使用 mutex 保护共享数据 |
| 死锁 | 避免嵌套锁,按固定顺序加锁 |
| 资源泄漏 | 使用 pthread_join 或 pthread_detach |
| 线程不安全函数 | 使用可重入版本(如 strtok_r) |
| 性能瓶颈 | 减少锁粒度,使用读写锁 |
✅ 十一、调试工具
valgrind --tool=helgrind:检测数据竞争、死锁gdb:调试多线程程序(info threads,thread N)
✅ 总结:pthreads 核心要点
| 操作 | 函数 |
|---|---|
| 创建线程 | pthread_create |
| 等待线程 | pthread_join |
| 分离线程 | pthread_detach |
| 互斥锁 | pthread_mutex_lock/unlock |
| 条件变量 | pthread_cond_wait/signal |
| 线程局部存储 | pthread_key_create / __thread |
| 取消线程 | pthread_cancel + 清理函数 |
✅ 建议:
- 优先使用
pthreads进行 Linux/macOS 多线程开发。 - 避免全局变量,使用参数传递数据。
- 尽量使用
pthread_join回收资源,避免分离线程滥用。
需要我提供一个 线程池(Thread Pool) 的完整实现示例吗?这是高性能服务器的常见模式。
POSIX线程编程核心指南
1953

被折叠的 条评论
为什么被折叠?



