【Linux】线程等待与分离

线程等待

为什么需要线程等待?

  • 已经退出的线程,其空间没有被释放,仍然在进程的地址空间内。
  • 创建新的线程不会复⽤刚才退出线程的地址空间。

线程退出也需要保存自己的退出返回值,因此线程也需要等待。只有线程处于joinable状态,这个线程才会被阻塞(joinable线程默认属性)。

功能:等待线程结束
原型
 int pthread_join(pthread_t thread, void **value_ptr);
参数
 thread:线程ID
 value_ptr:它指向⼀个指针,后者指向线程的返回值
返回值:成功返回0;失败返回错误码

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

  • 1. 如果thread线程通过return返回,value_ ptr所指向的单元⾥存放的是thread线程函数的返回值。
  • 2. 如果thread线程被别的线程调⽤pthread_ cancel异常终掉,value_ ptr所指向的单元⾥存放的是常数PTHREAD_ CANCELED。
  • 3. 如果thread线程是⾃⼰调⽤pthreadexit终⽌的,valueptr所指向的单元存放的是传给pthread_exit的参数。
  • 4. 如果对thread线程的终⽌状态不感兴趣,可以传NULL给value_ ptr参数。
#include <stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#include<errno.h>
void* thr_start(void* arg)
{
    printf("arg:%d\n",(int)arg);
    sleep(10);
    return NULL;
}

int main()
{
    pthread_t tid;
    int ret = pthread_create(&tid, NULL, thr_start, (void*)88);

    if(ret != 0)
    {
        printf("cteate pthread error\n");
        return -1;
    }

    sleep(2);
    pthread_cancel(tid);//PTHREAD_CANCELED
    char* retval;
    ret = pthread_join(tid, (void**)&retval);
    if(ret == EINVAL)
    {
        printf(""pthread is not joinable\n");
    }

    printf("--------------[%d]\n",(int)retval);
    return 0;
}

运行结果:

由于是静态图,所以等待过程看不见,不过可以看出,如果thread线程被别的线程调⽤pthread_ cancel异常终掉,value_ ptr所指向的单元⾥存放的是常数PTHREAD_ CANCELED。这个常数的值是-1.

分离线程

  • 默认情况下,新创建的线程是joinable的,线程退出后,需要对其进⾏pthread_join操作,否则⽆法释放资源,从⽽造成系统泄漏。
  • 如果不关⼼线程的返回值,join是⼀种负担,这个时候,我们可以告诉系统,当线程退出时,⾃动释放线程资源。

线程有一个属性,这个属性可以为-joinable/detach
 joinable是线程的默认属性,表示线程退出后需要被等待,获取返回值,允许操作系系统回收资源
 detach是需要重新设置的属性,表示线程退出后将直接释放资源,也就意味着线程无法被等待。
线程的这个属性只能选择其一;

int pthread_detach(pthread_t thread);

可以是线程组内其他线程对目标线程进⾏分离,也可以是线程⾃⼰分离:

pthread_detach(pthread_self());

joinable和分离是冲突的,⼀个 线程不能既是joinable⼜是分离的。

#include <stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#include<errno.h>
void* thr_start(void* arg)
{
    pthread_detach(pthread_self());
    printf("arg:%d\n",(int)arg);
    sleep(10);
    return NULL;
}

int main()
{
    pthread_t tid;
    int ret = pthread_create(&tid, NULL, thr_start, (void*)88);

    if(ret != 0)
    {
        printf("cteate pthread error\n");
        return -1;
    }

    sleep(2);
    pthread_cancel(tid);//PTHREAD_CANCELED
    char* retval;
    ret = pthread_join(tid, (void**)&retval);
    if(ret == EINVAL)
    {
        printf("pthread is not joinable\n");
    }

    printf("--------------[%d]\n",(int)retval);
    return 0;
}

很明显,当把子线程的属性重新设置后,就不在是一个需要等待的线程,所以用线程等待函数pthread_join失败。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值