首页 > 程序开发 > 综合编程 > 其他综合 >

线程终止、等待、分离的方式讲解

2018-04-11

线程终止、等待、分离的方式讲解。一、线程终止:线程终止有三种方式,包括:1 从线程函数return(对主线程不可使用),从main函数return相当于调用exit。2 线程可以调用pthread_exit终止自己。

一、线程终止

线程终止有三种方式,包括:

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              
 #include 
 #include 
 #include 
 #include 

 //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 
#include 
#include 
#include 
#include 

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;
}    

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

相关文章
最新文章
热点推荐