1.线程相关概念
在Linux系统中,线程(Threads)是指进程内部的轻量级执行单元。轻量级的进程(LWP:light weight process),在Linux环境下线程的本质仍是进程。进程:拥有独立的地址空间,拥有PCB,相当于独居。线程:有PCB,但没有独立的地址空间,多个线程共享进程空间,相当于合租。
在Linux操作系统下:
- 线程:最小的执行单位
- 进程:最小分配资源单位,可看成是只有一个线程的进程。
线程的特点:
- 类Unix系统中,早期是没有“线程”概念的,80年代才引入,借助进程机制实现出了线程的概念。因此在这类系统中,进程和线程关系密切。
- 线程是轻量级进程(light-weight process),也有PCB,创建线程使用的底层函数和进程一样,都是clone,实际上,无论是创建进程的fork,还是创建线程的pthread_create,底层实现都是调用同一个内核函数 clone。如果复制对方的地址空间,那么就产出一个“进程”;如果共享对方的地址空间,就产生一个“线程”。
- 从内核里看进程和线程是一样的,都有各自不同的PCB.
- 进程可以蜕变成线程
- 在linux下,线程最是小的执行单位;进程是最小的分配资源单位
共享的资源
-
地址空间:
- 所有线程都共享相同的虚拟地址空间。这意味着它们可以直接访问同一进程中的全局变量、静态变量、动态分配的堆内存等。
-
文件描述符:
- 打开的文件、网络连接等文件描述符是进程级别的资源,所有线程可以共享访问。
-
信号处理器:
- 进程级别的信号处理器和信号处理函数是所有线程共享的。
-
进程相关的属性:
- 包括进程ID(PID)、进程组ID(PGID)、会话ID(SID)等进程级别的标识和属性。
不共享的资源
-
线程特有的资源:
- 每个线程有独立的线程ID(TID),线程本地存储(Thread Local Storage, TLS),和线程特有的寄存器上下文(包括栈指针、程序计数器等)。
-
栈空间:
- 每个线程都有自己的栈空间,用于存储函数调用的局部变量和临时数据。栈空间是线程私有的,不同线程之间不能直接访问。
-
线程控制块(TCB):
- 每个线程有自己的线程控制块,用于存储线程的状态、调度信息、优先级等。这些信息在操作系统内核中管理和维护,不共享给其他线程。
-
线程局部存储(Thread Local Storage, TLS):
- 线程可以有自己的TLS,可以存储线程特定的数据,对其他线程不可见。
优缺点
优点:
-
响应速度快:由于线程共享相同的地址空间,线程间的通信和数据传递速度快,适合需要快速响应的应用场景。
-
资源开销小:创建和销毁线程的开销相对较小,因为线程共享大部分资源,不需要像进程那样复制整个地址空间。
-
并发性高:线程能够更有效地利用多核处理器,提高程序的并发度和性能。
-
简化编程:相较于进程间通信(IPC),线程间的数据共享和通信更为简单直接,适合于需要频繁数据交换的应用。
缺点:
-
共享数据风险:线程之间共享的数据需要通过同步机制来保护,否则可能导致竞态条件和数据不一致的问题。
-
调试困难:由于多个线程共享相同的地址空间,线程之间的交互和错误追踪可能比较复杂,增加了调试的难度。
-
稳定性:一个线程的崩溃可能会影响整个进程的稳定性,因为它们共享相同的进程资源。
2.线程操作常用库函数
2.1.线程的创建和销毁
2.1.1.pthread_create()
pthread_create
函数用于创建一个新的线程,并将执行的起始地址指定为一个函数。新线程会在该函数开始执行时启动。
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
参数:
thread:一个指向 pthread_t 类型变量的指针,用于存储新创建线程的标识符。
attr:线程的属性,通常为 NULL,表示使用默认属性。
start_routine:指向线程函数的指针,即线程在启动时要执行的函数地址。
arg:传递给线程函数的参数,类型为 void *。
返回值:
成功情况下,pthread_create 返回值为 0,表示线程创建成功。
如果出现错误,返回的值为正整数,可以通过 errno 全局变量获取具体的错误码。
- 线程函数
start_routine
必须具有void *
类型的参数,并且返回void *
类型的指针。 - 被创建的线程是可执行的,但不保证立即运行。线程的运行取决于调度器的调度。
- 新线程从调用
pthread_create
的点开始执行start_routine
函数,传递的参数是arg
。 - 可以通过
pthread_join
函数等待新创建的线程结束,并获取其返回值。
示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
// 线程执行的函数,打印传入的字符串
void *thread_function(void *arg) {
char *message = (char *)arg; // 将传入的参数转换为字符串指针
printf("Thread message: %s\n", message); // 打印线程接收到的消息
pthread_exit(NULL); // 退出线程,返回 NULL
}
int main() {
pthread_t thread_id; // 线程标识符
char *message = "Hello, this is the thread message!"; // 线程的消息
// 创建线程,传递参数 message 给 thread_function 函数
int result = pthread_create(&thread_id, NULL, thread_function, (void *)message);
if (result) {
printf("Error - pthread_create() return code: %d\n", result); // 打印错误码
exit(EXIT_FAILURE); // 退出程序
}
printf("Thread created successfully\n");
// 等待线程结束
pthread_join(thread_id, NULL);
printf("Thread joined\n");
return 0;
}
2.1.2.pthread_join()
pthread_join
函数用于等待一个指定的线程结束,并获取其返回值(如果有)。它会阻塞当前线程,直到目标线程完成执行并回收其资源。
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
参数:
thread:要等待的线程的标识符,即由 pthread_create 返回的线程ID。
retval:用来存储线程函数的返回值的地址的指针。如果不需要线程的返回值,可以将其设置为 NULL。
返回值:
成功情况下,pthread_join 返回值为 0,表示等待线程成功结束。
如果出现错误,返回的值为正整数,可以通过 errno 全局变量获取具体的错误码。
- 当调用
pthread_join
时,如果目标线程尚未结束,调用线程将会阻塞直到目标线程结束为止。 - 一旦目标线程结束,其资源将被回收,包括线程 ID 和任何动态分配的资源。
- 可以通过
pthread_detach
将线程设置为分离状态,这样线程结束后会自动回收资源,不需要调用pthread_join
。
示例代码:
下面是一个示例代码,演示了如何使用 pthread_create
创建一个新线程,然后使用 pthread_join
函数等待该线程结束,并获取其返回值。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
// 线程执行的函数,返回一个整数
void *thread_function(void *arg) {
int *param = (int *)arg; // 将传入的参数转换为整型指针
int *result = malloc(sizeof(int)); // 分配内存用于存放返回结果
*result = *param * 2; // 简单示例:计算传入参数的两倍
pthread_exit(result); // 退出线程,返回结果
}
int main() {
pthread_t thread_id; // 线程标识符
int param = 5; // 传递给线程函数的参数
void *thread_result; // 用于存放线程函数的返回结果
// 创建线程,传递参数 param 给 thread_function 函数
int result = pthread_create(&thread_id, NULL, thread_function, (void *)¶m);
if (result != 0) {
perror("Thread creation failed"); // 打印错误信息
exit(EXIT_FAILURE); // 退出程序
}
printf("Thread created successfully\n");
// 等待线程结束,并获取返回结果
result = pthread_join(thread_id, &thread_result);
if (result != 0) {
perror("Thread join failed"); // 打印错误信息
exit(EXIT_FAILURE); // 退出程序
}
printf("Thread joined successfully\n");
// 打印线程函数返回的结果
int *result_ptr = (int *)thread_result;
printf("Thread returned: %d\n", *result_ptr);
// 释放线程函数中分配的内存
free(result_ptr);
return 0;
}
2.1.3.pthread_exit()
pthread_exit
函数用于终止调用它的线程,并可以返回一个指定的值。它可以用来退出线程的执行,并将一个值传递给等待该线程的其他线程。
#include <pthread.h>
void pthread_exit(void *retval);
参数:
retval:线程的返回值,类型为 void *。可以是任意类型的指针,通常是动态分配的内存或者其他需要返回的数据。
返回值:
pthread_exit 函数本身没有返回值(即返回类型为 void),它会终止当前线程的执行并将 retval 作为线程的返回值传递给等待该线程的其他线程。
- 当调用
pthread_exit
函数时,它会立即终止当前线程的执行,并在退出前执行一些清理工作(比如释放资源等)。 - 如果不调用
pthread_exit
而是从线程函数返回,那么线程将隐式调用pthread_exit
,并返回NULL
。 - 主线程可以调用
pthread_exit
来终止自己,但一般情况下,主线程会在main
函数结束时自动调用pthread_exit
。 - 被
pthread_exit
终止的线程的资源(比如内存)不会自动释放,需要其他线程通过pthread_join
或者在线程函数中手动释放。
示例代码:
下面是一个示例代码,展示了如何使用 pthread_exit
函数来退出线程,并传递一个结果给等待它的其他线程。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
// 线程执行的函数,返回一个整数
void *thread_function(void *arg) {
int *param = (int *)arg; // 将传入的参数转换为整型指针
int *result = malloc(sizeof(int)); // 分配内存用于存放返回结果
*result = *param * 2; // 简单示例:计算传入参数的两倍
pthread_exit(result); // 退出线程,返回结果
}
int main() {
pthread_t thread_id; // 线程标识符
int param = 5; // 传递给线程函数的参数
void *thread_result; // 用于存放线程函数的返回结果
// 创建线程,传递参数 param 给 thread_function 函数
int result = pthread_create(&thread_id, NULL, thread_function, (void *)¶m);
if (result != 0) {
perror("Thread creation failed"); // 打印错误信息
exit(EXIT_FAILURE); // 退出程序
}
printf("Thread created successfully\n");
// 等待线程结束,并获取返回结果
result = pthread_join(thread_id, &thread_result);
if (result != 0) {
perror("Thread join failed"); // 打印错误信息
exit(EXIT_FAILURE); // 退出程序
}
printf("Thread joined successfully\n");
// 打印线程函数返回的结果
int *result_ptr = (int *)thread_result;
printf("Thread returned: %d\n", *result_ptr);
// 释放线程函数中分配的内存
free(result_ptr);
pthread_exit(NULL); // 主线程调用 pthread_exit 终止自己
return 0; // 这行代码实际上不会被执行,因为主线程已经被终止
}
2.1.4.pthread_detach()
pthread_detach
函数用于将指定的线程标识符标记为“分离状态”,这样该线程结束后,其资源会自动释放,不再需要其他线程调用 pthread_join
来回收资源。
#include <pthread.h>
int pthread_detach(pthread_t thread);
参数:
thread:要标记为分离状态的线程的标识符,即由 pthread_create 返回的线程ID。
返回值:
成功情况下,pthread_detach 返回值为 0,表示成功将线程标记为分离状态。
如果出现错误,返回的值为正整数,可以通过 errno 全局变量获取具体的错误码。
- 被标记为分离状态的线程在结束时会自动释放其资源,无需其他线程调用
pthread_join
。 - 分离状态的线程不会阻塞主线程或其他线程的执行,它们会在后台独立运行。
- 一旦线程被标记为分离状态,就不能再改变其状态,即不能再使用
pthread_join
等函数来等待该线程结束。
示例代码:
下面是一个示例代码,演示了如何使用 pthread_detach
函数将一个新创建的线程标记为分离状态,以及该线程如何自动释放资源。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h> // 用于 sleep 函数
// 线程执行的函数,打印一条消息,然后退出
void *thread_function(void *arg) {
printf("Thread is running\n");
sleep(2); // 模拟线程执行一些任务
printf("Thread is done\n");
pthread_exit(NULL); // 退出线程
}
int main() {
pthread_t thread_id; // 线程标识符
// 创建线程,传递 NULL 属性,传递 NULL 参数
int result = pthread_create(&thread_id, NULL, thread_function, NULL);
if (result != 0) {
perror("Thread creation failed"); // 打印错误信息
exit(EXIT_FAILURE); // 退出程序
}
printf("Thread created successfully\n");
// 将线程标记为分离状态
result = pthread_detach(thread_id);
if (result != 0) {
perror("Thread detach failed"); // 打印错误信息
exit(EXIT_FAILURE); // 退出程序
}
printf("Thread detached successfully\n");
// 主线程继续执行其他任务
printf("Main thread is running...\n");
// 等待一段时间,确保线程有足够时间执行
sleep(3);
printf("Main thread is done\n");
return 0;
}
2.1.5.pthread_cancel()
pthread_cancel
函数用于请求取消指定的线程。取消请求不会立即终止目标线程的执行,而是设置一个取消状态,线程在合适的时机(如取消点)检查该状态并执行取消操作。
#include <pthread.h>
int pthread_cancel(pthread_t thread);
参数:
thread:要取消的线程的标识符,即由 pthread_create 返回的线程ID。
返回值:
成功情况下,pthread_cancel 返回值为 0,表示成功发送取消请求。
如果出现错误,返回的值为正整数,可以通过 errno 全局变量获取具体的错误码。
pthread_cancel
函数发送一个取消请求给目标线程,目标线程会在适当的时候(如取消点)响应这个请求。- 取消请求不是立即终止线程,而是设置一个取消状态,线程在取消点检查这个状态并决定如何响应(比如继续执行或者退出)。
- 线程可以设置取消状态为“立即取消”或者“推迟取消”。
- 默认情况下,线程处于“推迟取消”状态,可以通过
pthread_setcanceltype
函数设置取消类型。
示例代码:
下面是一个示例代码,演示了如何使用 pthread_cancel
函数发送取消请求,并演示线程如何响应取消请求。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h> // 用于 sleep 函数
// 线程执行的函数,执行一个简单的计数循环
void *thread_function(void *arg) {
int i;
// 设置线程取消状态为立即取消
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
for (i = 1; ; i++) {
printf("Thread counting: %d\n", i);
sleep(1); // 休眠1秒钟
}
pthread_exit(NULL); // 线程退出
}
int main() {
pthread_t thread_id; // 线程标识符
// 创建线程,传递 NULL 属性,传递 NULL 参数
int result = pthread_create(&thread_id, NULL, thread_function, NULL);
if (result != 0) {
perror("Thread creation failed"); // 打印错误信息
exit(EXIT_FAILURE); // 退出程序
}
printf("Thread created successfully\n");
// 主线程等待一段时间
sleep(5);
// 发送取消请求给线程
result = pthread_cancel(thread_id);
if (result != 0) {
perror("Thread cancel failed"); // 打印错误信息
exit(EXIT_FAILURE); // 退出程序
}
printf("Thread cancel request sent\n");
// 等待线程结束
result = pthread_join(thread_id, NULL);
if (result != 0) {
perror("Thread join failed"); // 打印错误信息
exit(EXIT_FAILURE); // 退出程序
}
printf("Thread joined successfully\n");
return 0;
}
2.2 线程属性设置与获取
2.2.1pthread_attr_init()和pthread_attr_destroy()
pthread_attr_init
函数用于初始化线程属性对象,以便后续设置线程的属性。
#include <pthread.h>
int pthread_attr_init(pthread_attr_t *attr);
参数:
attr:指向 pthread_attr_t 结构的指针,用于存储线程属性信息。这个结构在函数调用时会被初始化为默认值。
返回值:
成功情况下,返回值为 0,表示初始化线程属性成功。
如果出现错误,返回的值为正整数,可以通过 errno 全局变量获取具体的错误码。
- 在创建线程时,可以使用
pthread_attr_t
结构来指定特定的线程属性,例如线程的栈大小、调度策略等。 - 如果不显式调用
pthread_attr_init
来初始化pthread_attr_t
结构,系统会使用默认的属性。 - 使用
pthread_attr_init
初始化后,可以使用其他函数来修改属性,如pthread_attr_setstacksize
设置栈大小等。
pthread_attr_destroy
函数用于销毁线程属性对象,并释放相关资源。
#include <pthread.h>
int pthread_attr_destroy(pthread_attr_t *attr);
参数:
attr:指向 pthread_attr_t 结构的指针,要销毁的线程属性对象。
返回值:
成功情况下,返回值为 0,表示销毁线程属性成功。
如果出现错误,返回的值为正整数,可以通过 errno 全局变量获取具体的错误码。
- 调用
pthread_attr_destroy
后,不再能够使用attr
对象来设置或获取线程的属性。 - 应在不再需要线程属性对象时调用该函数,以释放相关资源。
pthread_attr_t
结构体用于指定和管理线程的属性,例如线程的栈大小、调度策略等。通过初始化和设置 pthread_attr_t
结构体,可以在创建线程时指定特定的属性。
常用的属性设置函数:
- 栈大小设置:使用
pthread_attr_setstacksize
函数设置线程的栈大小。 - 优先级设置:使用
pthread_attr_setschedparam
函数设置线程的调度参数。 - 分离状态设置:使用
pthread_attr_setdetachstate
函数设置线程的分离状态(可分离或非分离)。
示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *thread_function(void *arg) {
// 线程函数,这里简单地打印一条消息
printf("Thread is running\n");
pthread_exit(NULL);
}
int main() {
pthread_t thread_id;
pthread_attr_t attr; // 定义线程属性对象
size_t stack_size = 1024 * 1024; // 设置线程栈大小为 1 MB
int result;
// 初始化线程属性对象
result = pthread_attr_init(&attr);
if (result != 0) {
perror("Attribute initialization failed");
exit(EXIT_FAILURE);
}
// 设置线程的栈大小属性
result = pthread_attr_setstacksize(&attr, stack_size);
if (result != 0) {
perror("Setting stack size failed");
exit(EXIT_FAILURE);
}
// 创建线程,传递属性对象
result = pthread_create(&thread_id, &attr, thread_function, NULL);
if (result != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
printf("Thread created successfully\n");
// 等待线程结束
result = pthread_join(thread_id, NULL);
if (result != 0) {
perror("Thread join failed");
exit(EXIT_FAILURE);
}
printf("Thread joined successfully\n");
// 销毁线程属性对象
result = pthread_attr_destroy(&attr);
if (result != 0) {
perror("Attribute destruction failed");
exit(EXIT_FAILURE);
}
return 0;
}
2.2.2pthread_attr_getdetachstate()和pthread_attr_setdetachstate()
pthread_attr_getdetachstate
函数用于获取线程属性对象中的线程分离状态。
#include <pthread.h>
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
参数:
attr:指向 pthread_attr_t 结构的指针,要获取属性的线程属性对象。
detachstate:指向 int 类型的指针,用于存储获取到的线程分离状态(PTHREAD_CREATE_JOINABLE 或 PTHREAD_CREATE_DETACHED)。
返回值:
成功情况下,返回值为 0,表示获取线程分离状态成功。
如果出现错误,返回的值为正整数,可以通过 errno 全局变量获取具体的错误码。
- 线程的分离状态决定了线程结束时是否需要主线程调用
pthread_join
函数来等待其结束。 - 默认情况下,线程的分离状态是
PTHREAD_CREATE_JOINABLE
,即需要等待主线程调用pthread_join
。 - 可以通过
pthread_attr_setdetachstate
函数设置线程属性对象中的线程分离状态。
pthread_attr_setdetachstate
函数用于设置线程属性对象中的线程分离状态,即决定线程结束时是否需要等待其它线程调用 pthread_join
函数。
#include <pthread.h>
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
参数:
attr:指向 pthread_attr_t 结构的指针,要设置属性的线程属性对象。
detachstate:整数参数,指定线程的分离状态。可以是以下两个值之一:
PTHREAD_CREATE_JOINABLE:表示线程是可连接的,需要其它线程调用 pthread_join 等待其结束。
PTHREAD_CREATE_DETACHED:表示线程是分离的,结束时系统会自动回收资源,无需其它线程调用 pthread_join。
返回值:
成功情况下,返回值为 0,表示设置线程分离状态成功。
如果出现错误,返回的值为正整数,可以通过 errno 全局变量获取具体的错误码。
- 默认情况下,线程的分离状态是
PTHREAD_CREATE_JOINABLE
,即需要等待主线程调用pthread_join
。 - 如果将线程的分离状态设置为
PTHREAD_CREATE_DETACHED
,则不再需要主线程调用pthread_join
来等待线程结束,线程结束时会自动回收资源。 - 分离状态的设置必须在创建线程之前完成,一旦线程创建后,其属性就不能再被修改。
示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *thread_function(void *arg) {
printf("Thread is running\n");
pthread_exit(NULL); // 退出线程
}
int main() {
pthread_t thread_id; // 线程标识符
pthread_attr_t attr; // 线程属性对象
int result;
// 初始化线程属性对象
result = pthread_attr_init(&attr);
if (result != 0) {
perror("Attribute initialization failed");
exit(EXIT_FAILURE);
}
// 设置线程的分离状态为 detached
result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (result != 0) {
perror("Setting detach state failed");
exit(EXIT_FAILURE);
}
// 创建线程,传递属性对象
result = pthread_create(&thread_id, &attr, thread_function, NULL);
if (result != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
printf("Thread created successfully\n");
// 销毁线程属性对象
result = pthread_attr_destroy(&attr);
if (result != 0) {
perror("Attribute destruction failed");
exit(EXIT_FAILURE);
}
// 不再调用 pthread_join 等待线程结束,因为线程已经是 detached 状态
return 0;
}
2.3其他线程操作
2.3.1pthread_self()
pthread_self
函数用于获取当前线程的线程ID(pthread_t 类型的值),即用于获取调用线程的标识符。
#include <pthread.h>
pthread_t pthread_self(void);
参数:
该函数没有参数。
返回值:
返回当前线程的 pthread_t 类型的值,即线程的标识符。
pthread_t
类型通常是一个结构或整数类型,在不同的系统中可能有不同的定义。- 每个线程都有唯一的线程ID,可以通过
pthread_self
函数获取。 - 线程ID 可用于在多线程程序中唯一标识每个线程。
示例代码:
#include <stdio.h>
#include <pthread.h>
void *thread_function(void *arg) {
pthread_t tid = pthread_self(); // 获取当前线程的线程ID
printf("Thread ID: %lu\n", tid); // 打印线程ID(%lu 是无符号长整型的格式化输出)
pthread_exit(NULL);
}
int main() {
pthread_t thread_id;
int result;
// 创建线程
result = pthread_create(&thread_id, NULL, thread_function, NULL);
if (result != 0) {
perror("Thread creation failed");
return 1;
}
// 等待线程结束
result = pthread_join(thread_id, NULL);
if (result != 0) {
perror("Thread join failed");
return 1;
}
return 0;
}
2.3.2pthread_equal()
pthread_equal
函数用于比较两个线程的线程ID 是否相等。
#include <pthread.h>
int pthread_equal(pthread_t thread1, pthread_t thread2);
参数:
thread1:第一个要比较的线程ID(pthread_t 类型)。
thread2:第二个要比较的线程ID(pthread_t 类型)。
返回值:
如果 thread1 和 thread2 表示同一个线程,返回值为非零(通常是 1)。
如果 thread1 和 thread2 表示不同的线程,返回值为零。
pthread_equal
函数可以用于确定两个线程ID 是否指代同一个线程。- 线程ID 是由系统分配的唯一标识符,每个线程都有一个独特的线程ID。
- 此函数在多线程编程中很有用,例如在处理线程池或线程管理时,可以确保不会重复操作同一个线程。
示例代码:
#include <stdio.h>
#include <pthread.h>
void *thread_function(void *arg) {
pthread_t tid = pthread_self(); // 获取当前线程的线程ID
printf("Thread ID: %lu\n", tid); // 打印线程ID(%lu 是无符号长整型的格式化输出)
pthread_exit(NULL);
}
int main() {
pthread_t thread_id1, thread_id2;
int result;
// 创建线程1
result = pthread_create(&thread_id1, NULL, thread_function, NULL);
if (result != 0) {
perror("Thread creation failed");
return 1;
}
// 创建线程2
result = pthread_create(&thread_id2, NULL, thread_function, NULL);
if (result != 0) {
perror("Thread creation failed");
return 1;
}
// 等待线程1结束
result = pthread_join(thread_id1, NULL);
if (result != 0) {
perror("Thread join failed");
return 1;
}
// 等待线程2结束
result = pthread_join(thread_id2, NULL);
if (result != 0) {
perror("Thread join failed");
return 1;
}
// 比较线程ID
if (pthread_equal(thread_id1, thread_id2)) {
printf("Thread IDs are equal\n");
} else {
printf("Thread IDs are not equal\n");
}
return 0;
}