Chap3 进程与线程
Chap3 进程与线程
pthread_create()
pthread_create()
是 POSIX 线程(pthread)库中用于创建新线程的核心函数,其原型如下:
1
2
3
4
5
6
int pthread_create(
pthread_t *thread, // 线程标识符指针
const pthread_attr_t *attr, // 线程属性指针
void *(*start_routine)(void *), // 线程函数指针
void *arg // 传递给线程函数的参数
);
参数详解:
1. pthread_t *thread
- 作用:用于存储新线程的唯一标识符(线程ID)。
- 类型:
pthread_t
是一个不透明数据类型(具体实现可能为整数或结构体)。 - 使用方式:
1 2
pthread_t tid; // 定义线程ID变量 pthread_create(&tid, ...); // 创建线程后,tid会被填充
- 后续用途:可用于
pthread_join()
、pthread_detach()
等操作。
2. const pthread_attr_t *attr
- 作用:指定线程的属性(如栈大小、调度策略、分离状态等)。
- 类型:
pthread_attr_t
是线程属性结构体,需先初始化。 - 使用方式:
1 2 3 4 5
pthread_attr_t attr; pthread_attr_init(&attr); // 初始化属性 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // 设置属性 pthread_create(&tid, &attr, start_routine, arg); // 使用属性创建线程 pthread_attr_destroy(&attr); // 销毁属性对象
- 特殊值:
- 若为
NULL
,则使用默认属性(JOINABLE
、默认栈大小等)。
- 若为
3. void *(*start_routine)(void *)
- 作用:新线程启动后执行的函数(线程入口点)。
- 函数签名:必须为
void* func(void *)
形式。 - 示例:
1 2 3 4
void* thread_func(void *arg) { printf("Thread running, arg=%d\n", *(int*)arg); return NULL; // 返回值可通过 pthread_join() 获取 }
- 注意:
- 线程函数应返回
void*
,通常用于传递退出状态(可通过pthread_join()
接收)。 - 若线程函数直接返回,等价于调用
pthread_exit()
。 - 若线程函数不返回,则必须以
pthread_exit ();
结尾
- 线程函数应返回
4. void *arg
- 作用:传递给线程函数
start_routine
的参数。 - 类型:
void*
泛型指针,可传递任意数据类型(需强制转换)。 - 示例:
1 2
int value = 42; pthread_create(&tid, NULL, thread_func, &value); // 传递整数的地址
- 注意事项:
- 确保
arg
的生命周期覆盖线程的执行(避免传递栈变量的地址后主线程退出)。 - 若需传递多个参数,需封装为结构体。
- 确保
返回值
- 成功:返回
0
。 - 失败:返回错误码(非
errno
,需用strerror()
解析):1 2 3
if (pthread_create(&tid, NULL, thread_func, arg) != 0) { perror("pthread_create failed"); }
完整示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <pthread.h>
#include <stdio.h>
void* thread_func(void *arg) {
int num = *(int*)arg;
printf("Thread received: %d\n", num);
return (void*)(num + 1); // 返回计算结果
}
int main() {
pthread_t tid;
int arg_value = 42;
void *thread_result;
// 创建线程
if (pthread_create(&tid, NULL, thread_func, &arg_value) != 0) {
fprintf(stderr, "Thread creation failed\n");
return 1;
}
// 等待线程结束并获取返回值
pthread_join(tid, &thread_result);
printf("Thread returned: %ld\n", (long)thread_result);
return 0;
}
关键点总结
- 线程ID:通过
pthread_t
标识线程,后续用于管理。 - 属性控制:通过
attr
定制线程行为(如分离状态、栈大小)。 - 入口函数:线程从
start_routine
开始执行,返回值可被pthread_join
捕获。 - 参数传递:
arg
需注意生命周期和类型安全。
线程实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
// 全局变量用于存储数据和结果
int *numbers;
int count;
double average;
int maximum;
int minimum;
// 线程函数:计算平均值
void *calculate_average(void *arg) {
double sum = 0;
for (int i = 0; i < count; i++) {
sum += numbers[i];
}
average = sum / count;
pthread_exit(NULL);
}
// 线程函数:计算最大值
void *calculate_maximum(void *arg) {
maximum = numbers[0];
for (int i = 1; i < count; i++) {
if (numbers[i] > maximum) {
maximum = numbers[i];
}
}
pthread_exit(NULL);
}
// 线程函数:计算最小值
void *calculate_minimum(void *arg) {
minimum = numbers[0];
for (int i = 1; i < count; i++) {
if (numbers[i] < minimum) {
minimum = numbers[i];
}
}
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
if (argc < 2) {
printf("Usage: %s <number1> <number2> ... <numberN>\n", argv[0]);
return 1;
}
// 解析命令行参数
count = argc - 1;
numbers = (int *)malloc(count * sizeof(int));
for (int i = 0; i < count; i++) {
numbers[i] = atoi(argv[i + 1]);
}
// 创建三个线程
pthread_t threads[3];
pthread_create(&threads[0], NULL, calculate_average, NULL);
pthread_create(&threads[1], NULL, calculate_maximum, NULL);
pthread_create(&threads[2], NULL, calculate_minimum, NULL);
// 等待所有线程完成
for (int i = 0; i < 3; i++) {
pthread_join(threads[i], NULL);
}
// 输出结果
printf("The average value is %.0f\n", average);
printf("The maximum value is %d\n", maximum);
printf("The minimum value is %d\n", minimum);
// 释放内存
free(numbers);
return 0;
}
This post is licensed under CC BY 4.0 by the author.