Linux系统编程-线程(Thread)相关内容详解

1.线程相关概念

在Linux系统中,线程(Threads)是指进程内部的轻量级执行单元。轻量级的进程(LWP:light weight process),在Linux环境下线程的本质仍是进程。进程:拥有独立的地址空间,拥有PCB,相当于独居。线程:有PCB,但没有独立的地址空间,多个线程共享进程空间,相当于合租。

在Linux操作系统下:

  • 线程:最小的执行单位
  • 进程:最小分配资源单位,可看成是只有一个线程的进程。

线程的特点:

  • 类Unix系统中,早期是没有“线程”概念的,80年代才引入,借助进程机制实现出了线程的概念。因此在这类系统中,进程和线程关系密切。
  • 线程是轻量级进程(light-weight process),也有PCB,创建线程使用的底层函数和进程一样,都是clone,实际上,无论是创建进程的fork,还是创建线程的pthread_create,底层实现都是调用同一个内核函数 clone。如果复制对方的地址空间,那么就产出一个“进程”;如果共享对方的地址空间,就产生一个“线程”。
  • 从内核里看进程和线程是一样的,都有各自不同的PCB.
  • 进程可以蜕变成线程
  • 在linux下,线程最是小的执行单位;进程是最小的分配资源单位

共享的资源

  1. 地址空间

    • 所有线程都共享相同的虚拟地址空间。这意味着它们可以直接访问同一进程中的全局变量、静态变量、动态分配的堆内存等。
  2. 文件描述符

    • 打开的文件、网络连接等文件描述符是进程级别的资源,所有线程可以共享访问。
  3. 信号处理器

    • 进程级别的信号处理器和信号处理函数是所有线程共享的。
  4. 进程相关的属性

    • 包括进程ID(PID)、进程组ID(PGID)、会话ID(SID)等进程级别的标识和属性。

不共享的资源

  1. 线程特有的资源

    • 每个线程有独立的线程ID(TID),线程本地存储(Thread Local Storage, TLS),和线程特有的寄存器上下文(包括栈指针、程序计数器等)。
  2. 栈空间

    • 每个线程都有自己的栈空间,用于存储函数调用的局部变量和临时数据。栈空间是线程私有的,不同线程之间不能直接访问。
  3. 线程控制块(TCB)

    • 每个线程有自己的线程控制块,用于存储线程的状态、调度信息、优先级等。这些信息在操作系统内核中管理和维护,不共享给其他线程。
  4. 线程局部存储(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 *)&param);
    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 *)&param);
    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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值