如何根据flag结束线程并创建新线程-Deepseek

代码

 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
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

// 标志位,用于通知线程退出
volatile int flag = 0;

// 线程函数
void* thread_func(void* arg) {
    while (!flag) {
        printf("Thread is running...\n");
        sleep(1);
    }
    printf("Thread exiting...\n");
    pthread_exit(NULL);
}

int main() {
    pthread_t thread;
    int ret;

    // 创建线程
    ret = pthread_create(&thread, NULL, thread_func, NULL);
    if (ret != 0) {
        perror("pthread_create");
        exit(EXIT_FAILURE);
    }

    // 主线程等待一段时间
    sleep(5);

    // 设置标志位,通知线程退出
    flag = 1;

    // 等待线程结束并回收资源
    ret = pthread_join(thread, NULL);
    if (ret != 0) {
        perror("pthread_join");
        exit(EXIT_FAILURE);
    }

    printf("Thread has exited.\n");

    // 创建新线程
    flag = 0;  // 重置标志位
    ret = pthread_create(&thread, NULL, thread_func, NULL);
    if (ret != 0) {
        perror("pthread_create");
        exit(EXIT_FAILURE);
    }

    // 主线程等待一段时间
    sleep(5);

    // 设置标志位,通知新线程退出
    flag = 1;

    // 等待新线程结束并回收资源
    ret = pthread_join(thread, NULL);
    if (ret != 0) {
        perror("pthread_join");
        exit(EXIT_FAILURE);
    }

    printf("New thread has exited.\n");

    return 0;
}

关键点

标志位:使用volatile int flag通知线程退出。

pthread_join:确保线程正常退出并回收资源。

重置标志位:创建新线程前重置flag。

可以不需要等待5秒,线程创建后可以立即退出并收尸。关键在于如何正确管理线程的生命周期,确保线程能够正常退出并且资源被回收。以下是改进后的代码示例,去除了不必要的等待时间,并确保线程创建后可以立即退出并收尸

 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
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

// 标志位,用于通知线程退出
volatile int flag = 0;

// 线程函数
void* thread_func(void* arg) {
    while (!flag) {
        printf("Thread is running...\n");
        sleep(1);
    }
    printf("Thread exiting...\n");
    pthread_exit(NULL);
}

int main() {
    pthread_t thread;
    int ret;

    // 创建线程
    ret = pthread_create(&thread, NULL, thread_func, NULL);
    if (ret != 0) {
        perror("pthread_create");
        exit(EXIT_FAILURE);
    }

    // 立即设置标志位,通知线程退出
    flag = 1;

    // 等待线程结束并回收资源
    ret = pthread_join(thread, NULL);
    if (ret != 0) {
        perror("pthread_join");
        exit(EXIT_FAILURE);
    }

    printf("Thread has exited.\n");

    // 创建新线程
    flag = 0;  // 重置标志位
    ret = pthread_create(&thread, NULL, thread_func, NULL);
    if (ret != 0) {
        perror("pthread_create");
        exit(EXIT_FAILURE);
    }

    // 立即设置标志位,通知新线程退出
    flag = 1;

    // 等待新线程结束并回收资源
    ret = pthread_join(thread, NULL);
    if (ret != 0) {
        perror("pthread_join");
        exit(EXIT_FAILURE);
    }

    printf("New thread has exited.\n");

    return 0;
}

关键点

立即设置标志位:

在线程创建后,立即设置flag = 1,通知线程退出。

这样可以避免不必要的等待时间。

pthread_join:

使用pthread_join等待线程退出并回收资源。

即使线程立即退出,pthread_join也会确保资源被正确回收。

重置标志位:

在创建新线程之前,重置flag = 0,以确保新线程能够正常运行。

线程函数中的循环:

线程函数中的while (!flag)循环会检查标志位,如果flag为1,线程会立即退出。

总结

不需要固定的等待时间(如5秒),可以通过标志位立即通知线程退出。

使用pthread_join确保线程资源被回收,避免僵尸线程。

这种方法可以动态控制线程的生命周期,适用于需要频繁创建和销毁线程的场景。

正确处理线程中的动态内存

 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
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

// 线程数据结构体
typedef struct {
    int id;
    char* message;
} ThreadData;

// 线程函数
void* thread_func(void* arg) {
    ThreadData* data = (ThreadData*)arg;
    printf("Thread %d: %s\n", data->id, data->message);

    // 模拟线程工作
    sleep(2);

    // 释放动态分配的内存
    free(data->message);
    free(data);

    printf("Thread %d: Resources freed, exiting...\n", data->id);
    pthread_exit(NULL);
}

int main() {
    pthread_t thread;
    int ret;

    // 动态分配线程数据
    ThreadData* data = (ThreadData*)malloc(sizeof(ThreadData));
    if (!data) {
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    data->id = 1;
    data->message = (char*)malloc(50 * sizeof(char));
    if (!data->message) {
        perror("malloc");
        free(data);
        exit(EXIT_FAILURE);
    }
    snprintf(data->message, 50, "Hello from thread %d", data->id);

    // 创建线程
    ret = pthread_create(&thread, NULL, thread_func, data);
    if (ret != 0) {
        perror("pthread_create");
        free(data->message);
        free(data);
        exit(EXIT_FAILURE);
    }

    // 等待线程结束并回收资源
    ret = pthread_join(thread, NULL);
    if (ret != 0) {
        perror("pthread_join");
        exit(EXIT_FAILURE);
    }

    printf("Main: Thread has exited.\n");

    return 0;
}

关键代码解析

动态分配内存:

使用malloc为线程数据(ThreadData)和字符串(message)分配内存。

释放内存:

在线程退出前,调用free释放data->message和data。

线程退出:

线程退出时,确保所有动态分配的内存都被释放,避免内存泄漏。

使用清理函数(pthread_cleanup_push和pthread_cleanup_pop)

 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
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

// 线程数据结构体
typedef struct {
    int id;
    char* message;
} ThreadData;

// 清理函数
void cleanup_handler(void* arg) {
    ThreadData* data = (ThreadData*)arg;
    printf("Cleanup handler: Freeing resources for thread %d\n", data->id);
    free(data->message);
    free(data);
}

// 线程函数
void* thread_func(void* arg) {
    ThreadData* data = (ThreadData*)arg;

    // 注册清理函数
    pthread_cleanup_push(cleanup_handler, data);

    printf("Thread %d: %s\n", data->id, data->message);

    // 模拟线程工作
    sleep(2);

    // 弹出清理函数并执行(参数为1表示执行清理函数)
    pthread_cleanup_pop(1);

    pthread_exit(NULL);
}

int main() {
    pthread_t thread;
    int ret;

    // 动态分配线程数据
    ThreadData* data = (ThreadData*)malloc(sizeof(ThreadData));
    if (!data) {
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    data->id = 1;
    data->message = (char*)malloc(50 * sizeof(char));
    if (!data->message) {
        perror("malloc");
        free(data);
        exit(EXIT_FAILURE);
    }
    snprintf(data->message, 50, "Hello from thread %d", data->id);

    // 创建线程
    ret = pthread_create(&thread, NULL, thread_func, data);
    if (ret != 0) {
        perror("pthread_create");
        free(data->message);
        free(data);
        exit(EXIT_FAILURE);
    }

    // 等待线程结束并回收资源
    ret = pthread_join(thread, NULL);
    if (ret != 0) {
        perror("pthread_join");
        exit(EXIT_FAILURE);
    }

    printf("Main: Thread has exited.\n");

    return 0;
}

总结

未释放的内存不会阻止线程退出,但会导致内存泄漏。

在线程退出前,确保释放所有动态分配的内存。

可以使用清理函数(pthread_cleanup_push和pthread_cleanup_pop)确保资源在线程被取消时也能正确释放。

良好的资源管理是编写健壮多线程程序的关键。

pthread_cancel

pthread_cancel 是 POSIX 线程库中用于取消线程的函数。它允许一个线程请求取消另一个线程。被取消的线程会在下一个取消点(cancellation point)退出,或者在显式调用pthread_testcancel时退出。为了正确使用pthread_cancel,需要注意以下几点:

  1. pthread_cancel 的基本用法
  • 函数原型:
1
int pthread_cancel(pthread_t thread);
  • thread:要取消的线程 ID。
  • 返回值:成功返回 0,失败返回错误码。
  • 取消点:

    • 取消点是线程可以响应取消请求的地方。常见的取消点包括:

      • sleep、pthread_join、read、write 等阻塞函数。
      • 显式调用 pthread_testcancel。
  • 取消类型:

    • 线程的取消行为由取消类型(cancellation type)决定:
    • 延迟取消(Deferred cancellation):默认行为,线程只有在取消点才会响应取消请求。
    • 异步取消(Asynchronous cancellation):线程可以在任何时候被取消,但这种方式不安全,容易导致资源泄漏。
  1. pthread_cancel 的使用步骤
  • 设置线程的取消状态:

    • 使用 pthread_setcancelstate 设置线程是否允许被取消。
    • 使用 pthread_setcanceltype 设置取消类型(延迟取消或异步取消)。
  • 在线程中处理取消请求:

    • 如果线程需要清理资源,可以使用 pthread_cleanup_push 和 pthread_cleanup_pop 注册清理函数。
  • 在主线程中调用 pthread_cancel:

    • 主线程或其他线程可以调用 pthread_cancel 取消目标线程。
  • 等待线程退出并回收资源:

    • 使用 pthread_join 等待被取消的线程退出,并确保资源被正确回收。
  1. 完整示例代码

以下是一个综合示例,展示了如何使用 pthread_cancel 取消线程,并确保资源被正确释放:

 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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

// 线程数据结构体
typedef struct {
    int id;
    char* message;
} ThreadData;

// 清理函数
void cleanup_handler(void* arg) {
    ThreadData* data = (ThreadData*)arg;
    printf("Cleanup handler: Freeing resources for thread %d\n", data->id);
    free(data->message);
    free(data);
}

// 线程函数
void* thread_func(void* arg) {
    ThreadData* data = (ThreadData*)arg;

    // 注册清理函数
    pthread_cleanup_push(cleanup_handler, data);

    // 允许线程被取消
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);

    printf("Thread %d: %s\n", data->id, data->message);

    // 模拟线程工作
    while (1) {
        printf("Thread %d: Working...\n", data->id);
        sleep(1);

        // 显式检查取消请求
        pthread_testcancel();
    }

    // 弹出清理函数(不会执行,因为线程会被取消)
    pthread_cleanup_pop(0);

    pthread_exit(NULL);
}

int main() {
    pthread_t thread;
    int ret;

    // 动态分配线程数据
    ThreadData* data = (ThreadData*)malloc(sizeof(ThreadData));
    if (!data) {
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    data->id = 1;
    data->message = (char*)malloc(50 * sizeof(char));
    if (!data->message) {
        perror("malloc");
        free(data);
        exit(EXIT_FAILURE);
    }
    snprintf(data->message, 50, "Hello from thread %d", data->id);

    // 创建线程
    ret = pthread_create(&thread, NULL, thread_func, data);
    if (ret != 0) {
        perror("pthread_create");
        free(data->message);
        free(data);
        exit(EXIT_FAILURE);
    }

    // 主线程等待一段时间
    sleep(3);

    // 取消线程
    printf("Main: Cancelling thread %d...\n", data->id);
    ret = pthread_cancel(thread);
    if (ret != 0) {
        perror("pthread_cancel");
        exit(EXIT_FAILURE);
    }

    // 等待线程结束并回收资源
    ret = pthread_join(thread, NULL);
    if (ret != 0) {
        perror("pthread_join");
        exit(EXIT_FAILURE);
    }

    printf("Main: Thread has exited.\n");

    return 0;
}
  1. 注意事项
  • 资源泄漏:

    • 如果线程被取消时没有正确释放资源(如动态内存、文件描述符等),会导致资源泄漏。务必使用清理函数或手动释放资源。
  • 异步取消的风险:

    • 异步取消(PTHREAD_CANCEL_ASYNCHRONOUS)可能导致线程在任意时刻被取消,容易引发资源泄漏或数据不一致。除非必要,否则不要使用异步取消。
  • 取消点的选择:

    • 如果线程长时间运行而没有取消点,可以使用 pthread_testcancel 显式检查取消请求。

总结

  • pthread_cancel 是用于取消线程的函数,但需要配合清理函数和 pthread_join 使用,以确保资源被正确释放。
  • 使用 pthread_cleanup_push 和 pthread_cleanup_pop 注册清理函数,避免资源泄漏。
  • 默认的延迟取消是安全的,异步取消应谨慎使用。
  • 通过合理设计线程的取消逻辑,可以编写出健壮的多线程程序。

在 main 函数的 while 循环中根据 flag 标志动态创建或停止线程,并确保子线程的结构体和动态申请的内存正常释放

实现思路

  • 全局标志位:

    • 使用一个全局标志位(如 volatile int flag)控制线程的创建和停止。
  • 线程管理:

    • 当 flag 为 1 时,创建线程。
    • 当 flag 为 0 时,停止线程并确保资源释放。
  • 资源释放:

    • 使用 pthread_cleanup_push 和 pthread_cleanup_pop 注册清理函数,确保线程被取消时资源(如结构体和动态内存)被正确释放。
  • 线程同步:

    • 使用 pthread_join 等待线程退出,确保线程资源被回收。

完整代码示例

  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
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

// 全局标志位
volatile int flag = 0;

// 线程数据结构体
typedef struct {
    int id;
    char* message;
} ThreadData;

// 清理函数
void cleanup_handler(void* arg) {
    ThreadData* data = (ThreadData*)arg;
    printf("Cleanup handler: Freeing resources for thread %d\n", data->id);
    free(data->message); // 释放动态内存
    free(data);          // 释放结构体
}

// 线程函数
void* thread_func(void* arg) {
    ThreadData* data = (ThreadData*)arg;

    // 注册清理函数
    pthread_cleanup_push(cleanup_handler, data);

    // 允许线程被取消
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);

    printf("Thread %d: %s\n", data->id, data->message);

    // 模拟线程工作
    while (1) {
        printf("Thread %d: Working...\n", data->id);
        sleep(1);

        // 显式检查取消请求
        pthread_testcancel();
    }

    // 弹出清理函数(不会执行,因为线程会被取消)
    pthread_cleanup_pop(0);

    pthread_exit(NULL);
}

int main() {
    pthread_t thread = 0; // 线程 ID
    int thread_id = 0;    // 线程编号
    int ret;

    while (1) {
        if (flag == 1 && thread == 0) {
            // 创建线程
            ThreadData* data = (ThreadData*)malloc(sizeof(ThreadData));
            if (!data) {
                perror("malloc");
                exit(EXIT_FAILURE);
            }
            data->id = ++thread_id;
            data->message = (char*)malloc(50 * sizeof(char));
            if (!data->message) {
                perror("malloc");
                free(data);
                exit(EXIT_FAILURE);
            }
            snprintf(data->message, 50, "Hello from thread %d", data->id);

            ret = pthread_create(&thread, NULL, thread_func, data);
            if (ret != 0) {
                perror("pthread_create");
                free(data->message);
                free(data);
                exit(EXIT_FAILURE);
            }

            printf("Main: Created thread %d\n", data->id);
        } else if (flag == 0 && thread != 0) {
            // 停止线程
            printf("Main: Stopping thread %d...\n", thread_id);
            ret = pthread_cancel(thread);
            if (ret != 0) {
                perror("pthread_cancel");
                exit(EXIT_FAILURE);
            }

            // 等待线程退出并回收资源
            ret = pthread_join(thread, NULL);
            if (ret != 0) {
                perror("pthread_join");
                exit(EXIT_FAILURE);
            }

            printf("Main: Thread %d has exited.\n", thread_id);
            thread = 0; // 重置线程 ID
        }

        // 模拟主线程工作
        sleep(1);

        // 模拟 flag 变化
        static int counter = 0;
        counter++;
        if (counter % 5 == 0) {
            flag = !flag; // 切换 flag 状态
            printf("Main: Toggling flag to %d\n", flag);
        }
    }

    return 0;
}

代码解析

  • 全局标志位 flag:

    • flag 控制线程的创建和停止:

      • flag == 1:创建线程。
      • flag == 0:停止线程。
  • 线程创建:

    • 动态分配 ThreadData 结构体和 message 内存。
    • 使用 pthread_create 创建线程,并将 ThreadData 传递给线程函数。
  • 线程停止:

    • 使用 pthread_cancel 取消线程。
    • 使用 pthread_join 等待线程退出,确保资源被回收。
  • 清理函数:

    • 使用 pthread_cleanup_push 注册清理函数 cleanup_handler,确保线程被取消时资源被正确释放。
  • 主循环:

    • 主循环根据 flag 的值动态创建或停止线程。
    • 每 5 秒切换一次 flag 的状态,模拟控制逻辑。

总结

  • 通过全局标志位 flag 动态控制线程的创建和停止。
  • 使用 pthread_cleanup_push 和 pthread_cleanup_pop 确保线程资源被正确释放。
  • 使用 pthread_cancel 和 pthread_join 安全地停止线程并回收资源。
  • 这种方法适用于需要动态管理线程生命周期的场景,同时避免了资源泄漏和僵尸线程问题。

线程清理函数被调用的条件都有哪些

线程清理函数(通过 pthread_cleanup_push 注册)的调用条件是由 POSIX 线程库的行为定义的。清理函数会在以下情况下被调用:

  1. 线程被取消(pthread_cancel)

    • 如果线程收到取消请求(通过 pthread_cancel),并且线程的取消状态为 PTHREAD_CANCEL_ENABLE(默认状态),则线程会在下一个取消点退出。
    • 在线程退出之前,所有通过 pthread_cleanup_push 注册的清理函数会按照**后进先出(LIFO)**的顺序被调用。
  2. 线程显式调用 pthread_exit

    • 如果线程显式调用 pthread_exit 退出,所有通过 pthread_cleanup_push 注册的清理函数会按照**后进先出(LIFO)**的顺序被调用。
  3. 线程调用 pthread_cleanup_pop 并传递非零参数

    • 如果线程调用 pthread_cleanup_pop 并传递一个非零参数,则弹出的清理函数会立即执行。
    • 这种方式通常用于在某个特定条件下手动触发清理函数。
  4. 线程正常返回(从线程函数中返回)

    • 如果线程从线程函数中正常返回(即没有调用 pthread_exit 或 pthread_cancel),则不会调用清理函数。
    • 这是清理函数与 C++ 析构函数的一个重要区别:清理函数不会在线程正常返回时自动调用。
  5. 线程被分离(pthread_detach)

    • 如果线程被分离(通过 pthread_detach),则线程退出时会自动释放资源,但清理函数仍然会被调用(如果满足上述条件)。
  6. 线程因未捕获的异常退出

    • 如果线程因未捕获的异常(如段错误)退出,则清理函数不会被调用。
    • 这种情况下,线程的资源可能无法正确释放。

清理函数的调用顺序

清理函数的调用顺序是**后进先出(LIFO)**的,即最后注册的清理函数会最先被调用。例如:

1
2
3
4
5
6
7
8
pthread_cleanup_push(cleanup1, NULL);
pthread_cleanup_push(cleanup2, NULL);
pthread_cleanup_push(cleanup3, NULL);

// 清理函数的调用顺序是 cleanup3 -> cleanup2 -> cleanup1
pthread_cleanup_pop(1); // 调用 cleanup3
pthread_cleanup_pop(1); // 调用 cleanup2
pthread_cleanup_pop(1); // 调用 cleanup1

示例代码

 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
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

// 清理函数 1
void cleanup1(void* arg) {
    printf("Cleanup 1: Freeing resources...\n");
}

// 清理函数 2
void cleanup2(void* arg) {
    printf("Cleanup 2: Freeing resources...\n");
}

// 线程函数
void* thread_func(void* arg) {
    // 注册清理函数
    pthread_cleanup_push(cleanup1, NULL);
    pthread_cleanup_push(cleanup2, NULL);

    printf("Thread: Running...\n");

    // 模拟线程工作
    sleep(2);

    // 显式调用 pthread_exit
    printf("Thread: Calling pthread_exit...\n");
    pthread_exit(NULL);

    // 弹出清理函数(不会执行,因为线程已经退出)
    pthread_cleanup_pop(0);
    pthread_cleanup_pop(0);
}

int main() {
    pthread_t thread;
    int ret;

    // 创建线程
    ret = pthread_create(&thread, NULL, thread_func, NULL);
    if (ret != 0) {
        perror("pthread_create");
        exit(EXIT_FAILURE);
    }

    // 等待线程结束
    ret = pthread_join(thread, NULL);
    if (ret != 0) {
        perror("pthread_join");
        exit(EXIT_FAILURE);
    }

    printf("Main: Thread has exited.\n");

    return 0;
}

总结

清理函数被调用的条件包括:

  • 线程被取消(pthread_cancel)。
  • 线程显式调用 pthread_exit。
  • 线程调用 pthread_cleanup_pop 并传递非零参数。

清理函数不会在以下情况下被调用:

  • 线程正常返回(从线程函数中返回)。
  • 线程因未捕获的异常退出。

通过合理使用清理函数,可以确保线程退出时资源被正确释放,避免内存泄漏和资源浪费。