整理pthread库函数(线程)
📅 2026/8/1 15:48:40
👁️ 阅读次数
📝 编程学习
目录
- 1. 线程创建
- 2. 线程退出
- 3. 线程等待
- 4. 线程取消
- 5. 线程清理处理程序
- 6. 互斥锁(Mutex)
- 6.1 初始化
- 6.2 上锁与解锁
- 6.3 尝试上锁
- 6.4 性能测量(时间获取)
- 7. 自旋锁(Spin Lock)
- 8. 读写锁(Read-Write Lock)
- 9. 条件变量(Condition Variable)
1. 线程创建
函数原型:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);参数说明:
- thread:指向线程标识符(ID)的指针,用于获取新创建线程的 ID。
- attr:线程属性指针,传入 NULL 表示使用系统默认属性。可配置属性包括:
- 分离状态(Detach State):设为分离态后,线程终止时自动回收资源,无需主线程调用 pthread_join。
- 栈空间大小(Stack Size):可手动调整线程栈内存,既能缩小栈空间以提升高并发下的内存利用率,又能增大栈空间防止溢出。
- 调度策略与优先级(Scheduling Policy & Priority):允许配置 SCHED_FIFO 或 SCHED_RR 等实时调度算法并指定线程优先级,以满足高实时性或抢占式任务的需求。
- start_routine:线程入口函数指针(回调函数),相当于子线程的 main 函数,由操作系统调用。
- arg:传递给线程入口函数的参数,无参数时可传入 NULL。
2. 线程退出
线程退出的两种方式:
- 线程入口函数返回:在入口函数中执行
return (void*)value;。 - 显式调用退出函数:在任何位置调用
void pthread_exit(void *retval);。
3. 线程等待
函数原型:
int pthread_join(pthread_t thread, void **retval);功能:等待指定线程结束,并获取其返回值。
参数说明:
- thread:要等待的线程 ID。
- retval:指向线程返回值的二级指针。若不需要获取返回值,可传入 NULL。
4. 线程取消
取消线程:
int pthread_cancel(pthread_t thread);向指定线程发送取消请求。取消操作不会立即生效,线程会运行到最近的“取消点”时才退出。
设置取消点:
void pthread_testcancel(void);手动设置一个取消点,允许线程在此处检查并响应取消请求。
5. 线程清理处理程序
压入清理函数:
void pthread_cleanup_push(void (*routine)(void *), void *arg);弹出清理函数:
void pthread_cleanup_pop(int execute);说明:
pthread_cleanup_push用于注册一个清理函数,当线程被取消或调用pthread_exit时,该函数会被自动调用。pthread_cleanup_pop用于移除最近压入的清理函数。- 若
execute参数为 0,则只弹栈不执行清理函数。 - 若
execute参数大于 0,则弹栈并执行清理函数。
- 若
- 注意:
push与pop必须成对出现,且通常紧跟在可能分配资源的操作(如malloc)之后。
特殊行为:调用pthread_exit(NULL)会弹出所有已注册的清理函数,并依次执行每个清理函数。
6. 互斥锁(Mutex)
6.1 初始化
动态初始化:
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);- mutex:指向互斥锁变量的指针。
- attr:互斥锁属性指针,通常传入 NULL 表示默认属性。
静态初始化:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;6.2 上锁与解锁
int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex);6.3 尝试上锁
int pthread_mutex_trylock(pthread_mutex_t *mutex);尝试获取锁,若成功则返回 0;若锁已被占用,则立即返回 EBUSY,线程不会阻塞。
6.4 性能测量(时间获取)
int gettimeofday(struct timeval *tv, struct timezone *tz);用法示例:
struct timeval start, end; gettimeofday(&start, NULL); // ... 临界区代码 ... gettimeofday(&end, NULL); // 计算耗时(秒 + 微秒) long seconds = end.tv_sec - start.tv_sec; long useconds = end.tv_usec - start.tv_usec; double elapsed = seconds + useconds / 1000000.0;7. 自旋锁(Spin Lock)
概述:自旋锁是一种高性能、低延迟的互斥锁。当线程尝试获取锁失败时,不会进入休眠状态,而是在 CPU 上执行“忙等待”(Busy-waiting)循环,不断轮询直到锁被释放。
特点:
- 消除了内核态上下文切换的开销。
- 适用于临界区执行时间极短(纳秒/微秒级)的场景。
- 若临界区执行时间较长,会浪费大量 CPU 资源。
初始化函数:pthread_spin_init
8. 读写锁(Read-Write Lock)
概述:读写锁是一种针对“读多写少”并发场景优化的锁机制。
基本原则:
- 读读共享:多个线程可以同时持有读锁。
- 读写互斥:读锁与写锁互斥。
- 写写互斥:同一时间只能有一个线程持有写锁。
优势:在大量读取、少量更新的场景下,能显著提升系统吞吐量。
初始化函数:pthread_rwlock_init
9. 条件变量(Condition Variable)
概述:条件变量是一种线程同步机制,用于实现线程间的等待/通知模式。它允许线程在某个条件不满足时挂起等待,直到其他线程改变条件并发出通知。
核心函数:
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);功能:让当前线程休眠等待,直到某个特定条件成立(被其他线程唤醒)再继续执行。
调用时内部会按顺序做 3 件事:
- 解锁并休眠(原子操作):自动把传入的互斥锁 mutex 解锁,同时把当前线程放入 cond 的等待队列并让线程挂起休眠。
- 等待唤醒:线程处于阻塞状态,完全不消耗 CPU,直到其他线程发来唤醒信号。
- 被唤醒并重新加锁:被唤醒后,它会重新去抢 mutex 锁。抢锁成功后,
pthread_cond_wait函数才会正式返回,继续往下执行代码。
典型使用模式:
// 1. 先加锁保护共享资源 pthread_mutex_lock(&mutex); // 2. 使用 while 检查条件(防止虚假唤醒) while (queue_is_empty) { // 条件不满足,解锁并进入休眠;被唤醒后自动重新加锁返回 pthread_cond_wait(&cond, &mutex); } // 3. 此时一定满足条件,且已经持有锁,安全地处理资源 pop_data_from_queue(); // 4. 操作完毕,解锁 pthread_mutex_unlock(&mutex);相关函数:
int pthread_cond_signal(pthread_cond_t *cond);- 唤醒等待在该条件变量上的一个线程int pthread_cond_broadcast(pthread_cond_t *cond);- 唤醒等待在该条件变量上的所有线程int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);- 带超时的等待
编程学习
技术分享
实战经验