Post

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;
}

关键点总结

  1. 线程ID:通过 pthread_t 标识线程,后续用于管理。
  2. 属性控制:通过 attr 定制线程行为(如分离状态、栈大小)。
  3. 入口函数:线程从 start_routine 开始执行,返回值可被 pthread_join 捕获。
  4. 参数传递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.