Linux系统编程 | 线程原语(2)

pthread_join函数

函数原型:

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

函数返回值:

成功:0;失败:错误号

函数作用:

阻塞等待指定线程退出,并获取线程退出状态。其作用,对应进程中的waitpid() 函数。

函数参数:

thread:等待的线程ID;

retval:存储线程结束状态。由于pthread_exit函数的参数是void *,所以此处retval是void **类型。

#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>

typedef struct {
    char name[20];
    int age;
} stu_t;

void *tfn(void *arg)
{
    stu_t *student = (stu_t *)malloc(sizeof(stu_t));
    if (student == NULL) {
        printf("malloc failed!\n");
        pthread_exit((void *)(-1));
    }

    memset(student, 0, sizeof(stu_t));
    student->age = 20;
    memcpy(student->name, "Harry", strlen("Harry"));
    printf("This is a thread!\n");
    pthread_exit((void *)student);
    return NULL;
}

int main()
{
    pthread_t tid;
    stu_t *ret;

    pthread_create(&tid, NULL, tfn, NULL);
    pthread_join(tid, (void **)&ret);
    printf("This main thread, ret->name: %s, ret->age: %d\n", ret->name, ret->age);

    return 0;
}

调用该函数的线程将挂起等待,直到id为thread的线程终止。thread线程以不同的方法终止,通过pthread_join得到的终止状态是不同的,总结如下:

  1. 如果thread线程通过return返回,retval所指向的单元里存放的是thread线程函数的返回值。
  2. 如果thread线程被别的线程调用pthread_cancel异常终止掉,retval所指向的单元里存放的是常数PTHREAD_CANCELED。
  3. 如果thread线程是自己调用pthread_exit终止的,retval所指向的单元存放的是传给pthread_exit的参数。
  4. 如果对thread线程的终止状态不感兴趣,可以传NULL给retval参数。
  5. 回收子线程的任何不仅仅只能通过主线程进行,任何线程都可以回收指定线程。

pthread_detach函数

函数原型:

int pthread_detach(pthread_t thread);

返回值:

成功:0;失败:错误号

函数作用:

实现线程分离。进程中无对应函数。

线程分离状态:

指定该状态,线程主动与主控线程断开关系。线程结束后,其退出状态不由其他线程获取,而直接自己自动释放。如果其它线程调用pthread_join函数来回收该线程,将得到出错信息。这种机制在网络、多线程服务器经常使用。

#include <stdio.h>
#include <pthread.h>

void *thf(void *arg)
{
    printf("this is a thread\n");
    pthread_exit(NULL);
}

int main()
{
    pthread_t tid;
    int err;

    pthread_create(&tid, NULL, thf, NULL);
    pthread_detach(tid);
    err = pthread_join(tid, NULL);
    printf("pthread_join result: %d\n", err);
    return 0;
}

一般情况下,线程终止后,其终止状态一直保留到其它线程调用pthread_join获取它的状态为止。但是线程也可以被置为detach状态,这样的线程一旦终止就立刻回收它占用的所有资源,而不保留终止状态。

不能对一个已经处于detach状态的线程调用pthread_join,这样的调用将返回EINVAL错误。也就是说,如果已经对一个线程调用了pthread_detach就不能再调用pthread_join了。

pthread_cancel函数

函数原型:

int pthread_cancel(pthread_t thread);

返回值:

成功:0;失败:错误号

函数作用:

杀死(取消)指定线程。其作用,对应进程中 kill() 函数。

注意:线程的取消并不是立即生效的,而是需要等待线程到达某个取消点(检查点)才可以。

所谓的取消点,可以理解为:当线程执行到某一行时,会去检查自己是否被取消了。这一行对应的函数(通常是系统调用)就是取消点。

取消点:

是线程检查是否被取消,并按请求进行动作的一个位置。通常是一些系统调用,如:creat,open,pause,close,read,write等。执行命令man 7 pthreads可以查看具备这些取消点的系统调用列表。

可粗略认为一个系统调用(进入内核)即为一个取消点。如线程中没有取消点,可以通过调用pthreestcancel函数自行设置一个取消点。

被取消的线程,退出值定义在Linux的pthread库中。通常线程被取消后,返回的错误号是PTHREAD_CANCELED,对应的值是-1。该错误号可在头文件pthread.h中找到它的定义:#define PTHREAD_CANCELED ((void *) -1)。因此当我们对一个已经被取消的线程使用pthread_join回收时,得到的返回值为-1。

总结:终止某个线程而不终止整个进程,有三种方法:

  1. 从线程主函数return。这种方法对主控线程不适用,从main函数return相当于调用exit。
  2. 一个线程可以调用pthread_cancel终止同一进程中的另一个线程。
  3. 线程可以调用pthread_exit终止自己。

pthread_equal函数

函数原型:

int pthread_equal(pthread_t t1, pthread_t t2);

函数作用:

比较两个线程ID是否相等。

注意:目前Linux系统下pthread_t是long int类型的,但其它平台可能是结构体实现,所以比较两个线程ID是否相等不能简单使用==来进行。

---------------

我是良许,世界500强外企 Linux 开发工程师,专业生产 Linux 干货。欢迎关注我的公众号「良许Linux」,回复「1024」获取最新最全的技术资料,回复「入群」进入高手如云技术交流群。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

良许Linux

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值