多线程编程基础
在Linux操作系统中,多线程是实现并发编程的重要手段,而pthread(POSIX Threads)则是Linux下最常用的多线程编程接口,与传统的多进程相比,多线程具有轻量级、共享内存、切换开销小等优势,能够充分利用多核处理器的计算能力,提高程序的执行效率,本文将围绕pthread在Linux多线程编程中的应用,从基本概念、核心函数、同步机制到实践注意事项展开详细阐述。

pthread库的初始化与创建
pthread库是POSIX标准的线程实现,在Linux中默认已集成,使用时需包含头文件<pthread.h>并链接-pthread或-lpthread库,线程的创建通过pthread_create函数实现,其原型为:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg);
thread参数用于返回新创建线程的ID;attr指定线程属性(如栈大小、调度策略等),通常传入NULL表示使用默认属性;start_routine是线程的入口函数,其参数为arg,返回值为void*,创建一个打印“Hello from thread!”的线程:
#include <pthread.h>
#include <stdio.h>
void* thread_func(void* arg) {
printf("Hello from thread!\n");
return NULL;
}
int main() {
pthread_t tid;
pthread_create(&tid, NULL, thread_func, NULL);
pthread_join(tid, NULL); // 等待线程结束
return 0;
}
编译时需添加-pthread选项:gcc -o thread_test thread_test.c -pthread。
线程的终止与资源回收
线程的终止方式多样:入口函数执行并返回void*指针、调用pthread_exit函数、被其他线程取消或整个进程终止,若需等待线程结束并回收资源,可使用pthread_join函数:
int pthread_join(pthread_t thread, void **retval);
该函数会阻塞调用线程,直到目标线程终止,并通过retval返回目标线程的退出值,上述代码中pthread_join(tid, NULL)确保主线程等待子线程执行完毕。
若不需要获取线程退出值,可使用pthread_detach将线程设置为分离状态,线程结束后自动释放资源,无需主线程回收:
pthread_detach(tid);
分离状态的线程不可被pthread_join等待,适用于“即创建即运行”的后台任务。

线程同步机制
多线程共享进程资源(如全局变量、堆内存)时,若多个线程同时访问或修改同一数据,会导致数据不一致问题,此时需通过同步机制保证线程安全。
互斥锁(Mutex)
互斥锁是最常用的同步工具,通过加锁和解锁操作实现资源的互斥访问,核心函数包括:
pthread_mutex_init:初始化互斥锁,可指定属性(如PTHREAD_MUTEX_DEFAULT)。pthread_mutex_lock:加锁,若锁已被占用则阻塞等待。pthread_mutex_unlock:解锁,唤醒其他等待线程。pthread_mutex_destroy:销毁互斥锁。
用互斥锁保护共享变量counter:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int counter = 0;
void* increment(void* arg) {
for (int i = 0; i < 10000; i++) {
pthread_mutex_lock(&mutex);
counter++;
pthread_mutex_unlock(&mutex);
}
return NULL;
}
条件变量(Condition Variable)
条件变量与互斥锁配合使用,允许线程在满足特定条件时才执行操作,避免忙等待,典型流程为:
- 加锁;
- 检查条件,若不满足则调用
pthread_cond_wait等待(该函数会自动解锁并阻塞); - 其他线程修改条件后调用
pthread_cond_signal或pthread_cond_broadcast唤醒等待线程; - 唤醒后重新加锁并再次检查条件。
生产者-消费者模型中的条件变量应用:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int buffer = 0;
void* producer(void* arg) {
pthread_mutex_lock(&mutex);
buffer = 1; // 生产数据
pthread_cond_signal(&cond); // 通知消费者
pthread_mutex_unlock(&mutex);
}
void* consumer(void* arg) {
pthread_mutex_lock(&mutex);
while (buffer == 0) { // 避免虚假唤醒
pthread_cond_wait(&cond, &mutex);
}
printf("Consumed: %d\n", buffer);
pthread_mutex_unlock(&mutex);
}
读写锁(Read-Write Lock)
读写锁适用于“读多写少”的场景,允许多个线程同时读数据,但写操作独占访问,分为读锁(共享锁)和写锁(排他锁),通过pthread_rwlock_t实现。

线程属性与调度
通过pthread_attr_t结构体可自定义线程属性,如栈大小、调度策略、优先级等,设置线程栈大小:
pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, 1024 * 1024); // 设置栈大小为1MB pthread_create(&tid, &attr, thread_func, NULL); pthread_attr_destroy(&attr);
Linux支持多种调度策略(SCHED_OTHER、SCHED_FIFO、SCHED_RR),其中SCHED_OTHER为默认分时调度策略,SCHED_FIFO和SCHED_RR为实时调度策略(需root权限)。
实践注意事项
- 避免死锁:使用互斥锁时需按固定顺序加锁,或采用
pthread_mutex_trylock尝试加锁(失败则释放已持有的锁并稍后重试)。 - 处理线程取消:默认情况下,线程可被
pthread_cancel取消,但需注意取消点(如pthread_cond_wait、malloc等函数),若需控制取消时机,可通过pthread_setcancelstate和pthread_setcanceltype设置取消状态和类型。 - 资源释放:分离线程的资源由系统自动回收,但非分离线程需确保
pthread_join被调用,避免内存泄漏。 - 信号处理:多进程中,信号默认由主线程处理,子线程需通过
pthread_sigmask屏蔽信号,或使用sigwait统一处理。
pthread作为Linux多线程编程的核心接口,提供了创建、同步、调度等完整功能,合理使用互斥锁、条件变量等同步机制,可有效避免数据竞争问题;掌握线程属性配置和资源管理技巧,能进一步提升程序的性能和稳定性,在实际开发中,需结合具体场景设计多线程模型,平衡并发效率与线程安全,从而充分发挥多核处理器的计算潜力。

















