《Linux C编程实战》笔记:线程终止

发布时间:2024年01月09日

Linux 下有两种方式可以使线程终止,一种是通过return从线程函数返回,第二种是通过调用pthread_exit()使线程退出

pthread_exit 是一个线程库中的函数,用于终止调用线程。该函数的原型如下:

#include <pthread.h>

void pthread_exit(void *retval);

  • retval 参数是一个指向线程的返回值的指针。这个返回值可以通过其他线程调用 pthread_join 函数来获取。

调用 pthread_exit 将会终止当前线程,并将 retval 的值传递给等待该线程的任何调用 pthread_join 的线程。如果线程没有被任何其他线程等待,它的资源将会在终止时被释放。

有两种特殊情况要注意:一种情况是, 在主线程中,如果从main函数返回或是调用了exit
函数退出主线程,则整个进程将终止,此时进程中所有线程也将终止,因此在主线程中不能过
早地从main函数返回;另种情是如果主线程调用pthread_ exit 函数,则仅仅是主线程消亡,进
程不会结束,进程内的其他线程也不会终止,直到所有线程结束,进程才会结束。

线程终止最重要的问题是资源释放的问题,特别是一些临界资源。临界资源在一段时间内只
能被一个线程所持有,当线程要使用临界资源时需提出请求,如果该资源未被使用则申请成功,
否则等待。临界资源使用完毕后要释放以便其他线程可以使用。例如,某线程要写-一个文件,在
写文件时一般不允许其他线程也对该文件执行写操作的,否则会导致文件数据混乱。这里的文件
就是一种临界资源。临界资源为一个线程所独占,当一个线程终止时,如果不释放其占有的临界
资源,则该资源会被认为还被已经退出的线程所使用,因而永远不会得到释放。如果一个线程在
等待使用这个临界资源,它就可能无限的等待下去,这就形成了死锁。

为此linux提供了一对函数用于自动释放资源

pthread_cleanup_push和pthread_cleanup_pop

pthread_cleanup_push通常与 pthread_cleanup_pop 一起使用。这对函数提供了一种在线程退出时执行特定操作的机制,而不是直接在线程函数中使用 return

以下是 pthread_cleanup_push 的原型:

#include <pthread.h>

void pthread_cleanup_push(void (*routine)(void *), void *arg);

  • routine 参数是一个指向清理函数的指针,该函数将在线程退出时执行。
  • arg 参数是传递给清理函数的参数。
 
 

#include <pthread.h>

void pthread_cleanup_pop(int execute);

  • execute 参数是一个整数值,如果 execute 的值为非零,则表示执行注册的清理函数;如果为零,则表示不执行清理函数。这提供了一种选择性地执行清理函数的机制。

意思即是线程退出时会执行routine指定的函数。

这两函数必须成对出现。

pthread_join函数

这个函数用来等待一个指定线程的结束。调用pthread_join的线程会被挂起等待某个线程终止

#include <pthread.h>

int pthread_join(pthread_t thread, void **retval);

  • thread 参数是要等待的线程的标识符。
  • retval 参数是一个指向指针的指针,用于接收目标线程的退出状态。

调用 pthread_join 的线程会一直阻塞,直到指定的线程(通过 thread 参数指定)退出。一旦目标线程退出,pthread_join 会解除阻塞,并将目标线程的退出状态存储在 retval 指向的位置。

一个线程只能被一个线程等待,不能多个线程都等待同一个线程。

同时,被等待的那个线程不能说detached的状态,即分离状态。对某个线程调用pthread_detach可使它变为detached状态。这时该线程在后台运行,会自动释放资源。

一个joinable线程所占用的内存仅当有线程对其执行了pthread_join才会释放。

所以一个线程要么是detached,要么通过pthread_join来回收它的资源。

示例程序

书上的示例程序好像不太对,我改了一下。

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
void *assistthread(void *arg){
    printf("i am helping to do some jobs\n");
    sleep(3);
    int *result=(int *)malloc(sizeof(int));
    *result=42;
    pthread_exit((void *)result);
}
int main(){
    pthread_t assistthid;
    int *status;
    pthread_create(&assistthid,nullptr,assistthread,nullptr);
    pthread_join(assistthid,(void **)&status);
    printf("assistthread's exit is caused %d\n",*status);
    free(status);
    return 0;    
}

可以看到主线程通过status来接受assist线程通过pthread_exit传出来的结束状态。

文章来源:https://blog.csdn.net/ouliten/article/details/135479048
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。