线程终止、等待、分离

一、线程终止

线程终止有三种方式,包括:
1.从线程函数return(对主线程不可使用),从main函数return相当于调用exit。
2.线程可以调用pthread_exit终止自己。
3.一个线程可以调用pthread_cancel终止同一进程中的另外一个线程。

我们来认识几个函数:
pthread_exit函数
用来终止进程,参数是void*类型,无返回值。
注意:return和pthread_exit返回的指针所指向的内存单元必须是全局的或者是malloc分配的,因为线程栈是私有的,当其他线程的得到这个函数的时候,该线程已经退出。

pthread_cancel函数
用来取消一个执行中的进程,成功返回0,失败返回错误码。
线程取消返回PTHREAD_CANCELED,是一个宏。
这个宏具体是什么呢?我们查找后发现是将-1转化为(void*)类型返回。

线程退出只有两种情况;
1.代码跑完,结果正确;
2.代码跑完,结果错误。
注意:和进程不同的是线程退出不包括线程异常退出,不会因为一个线程异常等待,只要有一个线程异常,主线程直接挂,不会等待

二、线程等待

为什么需要线程等待?
在学习进程时,我们说过父进程通过wait函数或waitpid函数等待子进程回收子进程的资源,获取子进程的退出信息,如果父进程没有等待,则会造成僵尸进程,子进程的描述符仍然保存在系统中。
线程也是一样的,如果不等待,则会造成类似僵尸线程的状况。已经退出的线程,其空间没有被释放,仍然在进程的地址空间内,创建的新线程不会复用刚才退出线程的地址空间。

代码实现:

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

 //return
 void *func1(void *arg){
     int *p = (int*)malloc(sizeof(int));
     *p = 2;
     return (void*)p;
 }

 //pthread_exit
 void *func2(void *arg){
     int *p = (int*)malloc(sizeof(int));
     *p = 2;
     pthread_exit((void*)p);
 }

 void *func3(void *arg){
     while(1){
         printf("thread 3 is running...\n");
         sleep(1);
     }
     return NULL;
 }
 int main()
 {
     pthread_t tid;
     void *ret;

     //thread 1 return
     pthread_create(&tid, NULL, func1, NULL);
     pthread_join(tid, &ret);
     printf("thread return, thread id %lu,return code:%d\n", tid, *(int*)ret);
     free(ret);

     //thread 2 exit
     pthread_create(&tid, NULL, func2, NULL);
     pthread_join(tid, &ret);
     printf("thread return, thread id %lu,return code:%d\n", tid, *(int*)ret);
     free(ret);

     //thread 3 cancel by other
     pthread_create(&tid, NULL, func3, NULL);                                  
     sleep(2);
     pthread_cancel(tid);
     pthread_join(tid, &ret);
     if(ret == PTHREAD_CANCELED){
         printf("thread return, thread id %lu,return code: PTHREAD_CANCELED\n", tid);
      }else{
          printf("thread return, thread id %lu,return code:NULL", tid);
      }

      while(1)
      {
          printf("I am main thread\n");
          sleep(1);
      }

      return 0;
  }      

这里写图片描述

三、线程分离

1.线程的状态分为两种:可结合的(joinable)和分离的(detached),其中默认情况下新创建的线程是可结合的

2.线程退出后,需要对其进行pthread_join操作否则无法释放资源,从而造成系统泄露。若将线程分离,则该线程是不需要join的(即不能被其他线程回收其资源和杀死),运行完毕后,系统会自动回收

3.线程分离可以是主线程将其分离,也可以是线程自己将自己分离

4.若分离的线程异常进程也会终止。因为线程分离是指资源层面上的分离,分离特性仅仅基于不出问题的情况

我们来认识几个函数:
pthread_detach函数
用于分离一个线程,分离成功返回0,分离失败返回错误码。
这里写图片描述

代码实现线程分离
这里写图片描述
这里写图片描述
由结果可知,将创建的线程分离出去后,就不需要join了

也可以创建出多个线程,用其他线程对该线程进程分离。如下:

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

void *func1(void *arg)
{
    pthread_exit((void*)0);
}

void *func2(void *arg)
{
    pthread_exit((void*)0);                                                                     
}

int main()
{
    pthread_t tid1, tid2;
    pthread_create(&tid1, NULL, func1, NULL);
    pthread_create(&tid2, NULL, func2, NULL);

    pthread_detach(tid1);
    if(pthread_join(tid1, NULL) == 0){
        printf("thread1 wait sucess\n");
    }else{
        printf("thread1 wait failed\n");
    }


    if(pthread_join(tid2, NULL) == 0){
        printf("thread2 wait sucess\n");
    }else{
        printf("thread2 wait failed\n");
}

    return 0;
}    

分离线程可以自己将自己分离,也可以其他线程对目标线程进行分离。分离后的线程不需要主线程等待,运行完后系统会对其进程回收。而可结合的线程需要主线程进程等待,对该进程进行资源释放。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值