您好,登录后才能下订单哦!
# Linux pthread线程怎么创建与使用
## 一、线程基础概念
### 1.1 什么是线程
线程(Thread)是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程可以包含多个线程,这些线程共享进程的资源(如内存空间、文件描述符等),但每个线程拥有自己独立的栈空间和程序计数器。
与进程相比,线程具有以下特点:
- 创建和切换开销更小
- 共享相同的地址空间
- 通信更加高效
- 更适合并行计算任务
### 1.2 POSIX线程(pthread)
POSIX线程(通常称为pthread)是IEEE POSIX 1003.1c标准定义的线程API,它是Unix-like系统中实现多线程编程的标准接口。Linux系统通过NPTL(Native POSIX Thread Library)实现了这一标准。
pthread库提供了以下核心功能:
- 线程创建与管理
- 线程同步(互斥锁、条件变量等)
- 线程特定数据
- 线程取消与控制
## 二、pthread线程创建
### 2.1 基本创建方法
在Linux中使用pthread_create函数创建线程:
```c
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
参数说明:
- thread
: 指向线程标识符的指针
- attr
: 线程属性,通常设为NULL使用默认属性
- start_routine
: 线程执行的函数
- arg
: 传递给线程函数的参数
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *thread_function(void *arg) {
int *value = (int *)arg;
printf("Thread received value: %d\n", *value);
return NULL;
}
int main() {
pthread_t thread_id;
int value = 42;
if (pthread_create(&thread_id, NULL, thread_function, &value) != 0) {
perror("pthread_create failed");
exit(EXIT_FLURE);
}
printf("Main thread created new thread\n");
// 等待线程结束
pthread_join(thread_id, NULL);
return 0;
}
pthread_attr_t结构体允许我们设置线程的各种属性:
pthread_attr_t attr;
pthread_attr_init(&attr); // 初始化属性
// 设置线程为分离状态
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
// 设置栈大小
size_t stack_size = 1024 * 1024; // 1MB
pthread_attr_setstacksize(&attr, stack_size);
// 创建带有自定义属性的线程
pthread_t thread;
pthread_create(&thread, &attr, thread_function, NULL);
// 销毁属性对象
pthread_attr_destroy(&attr);
互斥锁用于保护共享资源,防止多个线程同时访问:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *thread_func(void *arg) {
pthread_mutex_lock(&mutex);
// 临界区代码
pthread_mutex_unlock(&mutex);
return NULL;
}
条件变量用于线程间的通信:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int ready = 0;
// 等待线程
void *consumer(void *arg) {
pthread_mutex_lock(&mutex);
while (!ready) {
pthread_cond_wait(&cond, &mutex);
}
// 处理数据
pthread_mutex_unlock(&mutex);
return NULL;
}
// 通知线程
void *producer(void *arg) {
pthread_mutex_lock(&mutex);
ready = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
return NULL;
}
读写锁允许多个读操作同时进行,但写操作独占:
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
// 读锁
pthread_rwlock_rdlock(&rwlock);
// 读取共享数据
pthread_rwlock_unlock(&rwlock);
// 写锁
pthread_rwlock_wrlock(&rwlock);
// 修改共享数据
pthread_rwlock_unlock(&rwlock);
线程可以通过以下方式终止: 1. 从线程函数返回 2. 调用pthread_exit() 3. 被其他线程取消
void *thread_func(void *arg) {
// 方式1:返回
return NULL;
// 方式2:显式退出
pthread_exit(NULL);
}
pthread_join用于等待线程结束并获取其返回值:
pthread_t thread;
void *thread_result;
pthread_create(&thread, NULL, thread_function, NULL);
pthread_join(thread, &thread_result);
分离线程不需要被join,资源会自动回收:
pthread_t thread;
pthread_create(&thread, NULL, thread_function, NULL);
pthread_detach(thread);
pthread_t thread;
pthread_create(&thread, NULL, thread_function, NULL);
// 发送取消请求
pthread_cancel(thread);
// 线程函数中可以设置取消点
void *thread_func(void *arg) {
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
// 显式取消点
pthread_testcancel();
// 或者系统调用会自动成为取消点
sleep(1);
return NULL;
}
确保使用线程安全版本的函数: - rand() → rand_r() - strtok() → strtok_r() - localtime() → localtime_r()
死锁预防策略: 1. 按固定顺序获取锁 2. 使用trylock而非lock 3. 设置锁超时
// 尝试获取锁,避免死锁
if (pthread_mutex_trylock(&mutex) == 0) {
// 获取锁成功
pthread_mutex_unlock(&mutex);
} else {
// 处理获取锁失败的情况
}
使用__thread关键字或pthread_key_create创建线程特定数据:
// GCC扩展方式
static __thread int tls_var;
// POSIX标准方式
pthread_key_t key;
void destructor(void *value) {
free(value);
}
void init_key() {
pthread_key_create(&key, destructor);
}
void *thread_func(void *arg) {
int *data = malloc(sizeof(int));
*data = 42;
pthread_setspecific(key, data);
// 获取数据
int *value = pthread_getspecific(key);
printf("Thread local value: %d\n", *value);
return NULL;
}
线程池的基本结构:
typedef struct {
pthread_t *threads;
int thread_count;
task_queue_t *queue;
pthread_mutex_t lock;
pthread_cond_t notify;
int shutdown;
} thread_pool_t;
// 初始化线程池
thread_pool_t *thread_pool_create(int thread_count) {
thread_pool_t *pool = malloc(sizeof(thread_pool_t));
// 初始化各种成员和同步原语
// 创建worker线程
return pool;
}
// worker线程函数
void *worker_thread(void *arg) {
thread_pool_t *pool = (thread_pool_t *)arg;
while (1) {
pthread_mutex_lock(&pool->lock);
while (pool->queue->size == 0 && !pool->shutdown) {
pthread_cond_wait(&pool->notify, &pool->lock);
}
// 获取任务并执行
pthread_mutex_unlock(&pool->lock);
}
return NULL;
}
将线程绑定到特定CPU核心:
#include <sched.h>
void set_thread_affinity(pthread_t thread, int cpu_id) {
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(cpu_id, &cpuset);
pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
}
设置线程调度策略和优先级:
struct sched_param param;
param.sched_priority = sched_get_priority_max(SCHED_FIFO);
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
pthread_attr_setschedparam(&attr, ¶m);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_t thread;
pthread_create(&thread, &attr, realtime_thread_func, NULL);
最佳线程数量通常与CPU核心数相关:
#include <unistd.h>
int get_optimal_thread_count() {
long cores = sysconf(_SC_NPROCESSORS_ONLN);
return cores > 0 ? (int)cores : 1;
}
使用工具检测线程竞争: - Valgrind Helgrind - gdb thread apply all bt - perf工具
计算π值的蒙特卡洛方法:
typedef struct {
long long hits;
long long samples;
} thread_data_t;
void *monte_carlo(void *arg) {
thread_data_t *data = (thread_data_t *)arg;
unsigned int seed = time(NULL) ^ pthread_self();
for (long long i = 0; i < data->samples; i++) {
double x = (double)rand_r(&seed) / RAND_MAX;
double y = (double)rand_r(&seed) / RAND_MAX;
if (x*x + y*y <= 1.0) {
data->hits++;
}
}
return NULL;
}
double calculate_pi(int thread_count, long long total_samples) {
pthread_t threads[thread_count];
thread_data_t thread_data[thread_count];
long long samples_per_thread = total_samples / thread_count;
for (int i = 0; i < thread_count; i++) {
thread_data[i].hits = 0;
thread_data[i].samples = samples_per_thread;
pthread_create(&threads[i], NULL, monte_carlo, &thread_data[i]);
}
long long total_hits = 0;
for (int i = 0; i < thread_count; i++) {
pthread_join(threads[i], NULL);
total_hits += thread_data[i].hits;
}
return 4.0 * total_hits / total_samples;
}
#define BUFFER_SIZE 10
typedef struct {
int buffer[BUFFER_SIZE];
int count;
int in;
int out;
pthread_mutex_t mutex;
pthread_cond_t not_empty;
pthread_cond_t not_full;
} buffer_t;
void *producer(void *arg) {
buffer_t *buf = (buffer_t *)arg;
for (int i = 0; i < 100; i++) {
pthread_mutex_lock(&buf->mutex);
while (buf->count == BUFFER_SIZE) {
pthread_cond_wait(&buf->not_full, &buf->mutex);
}
buf->buffer[buf->in] = i;
buf->in = (buf->in + 1) % BUFFER_SIZE;
buf->count++;
pthread_cond_signal(&buf->not_empty);
pthread_mutex_unlock(&buf->mutex);
}
return NULL;
}
void *consumer(void *arg) {
buffer_t *buf = (buffer_t *)arg;
for (int i = 0; i < 100; i++) {
pthread_mutex_lock(&buf->mutex);
while (buf->count == 0) {
pthread_cond_wait(&buf->not_empty, &buf->mutex);
}
int item = buf->buffer[buf->out];
buf->out = (buf->out + 1) % BUFFER_SIZE;
buf->count--;
pthread_cond_signal(&buf->not_full);
pthread_mutex_unlock(&buf->mutex);
printf("Consumed: %d\n", item);
}
return NULL;
}
本文全面介绍了Linux下pthread线程的创建与使用方法,包括:
通过合理使用多线程技术,可以显著提高程序的并发性能和资源利用率。然而,多线程编程也带来了复杂性,需要开发者特别注意线程安全和同步问题。
掌握pthread编程是Linux系统开发的重要技能,希望本文能为读者提供全面的指导和参考。在实践中,建议从简单案例开始,逐步构建更复杂的多线程应用,同时充分利用调试工具来确保程序的正确性和稳定性。 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。