首页 > 代码库 > 线程学习笔记(二)

线程学习笔记(二)

5.终止线程

线程退出的方式有3种

1.线程体函数执行结束,用 pthread_create() 函数创建一个新线程的时候会执行一个函数,这个函数就是线程体函数,如果该函数执行完毕,那么线程退出,类似于住进程的 main() 函数返回。

2.线程被另一个线程取消。这种方法类似于一个进程被另一个进程调用kill()函数杀死。

3.线程自行退出,类似于线程调用一个 exit() 函数。

Linux系统中使用 pthread_exit(void *rval_ptr) 函数终止线程:

头文件:  #include <pthread.h> 

参数:     void *rval_ptr 是一个指向任意类型的指针,该指针指向的区域储存退出信息。

       功能:    该函数取消一个进程并返回一个指针 *rval_ptr ,该返回值是一个指针,其他线程可以得到该指针,得到该指针指向区域的值。

一个线程的结束信息可以有两种,一种是线程体函数返回的指针所指向的区域,,另一种是 pthread_exit(void *rval_ptr) 函数返回的指针 void *rval_ptr 所指向的区域。第一种方法可以获得线程体函数的返回值,第二种方法得到的是 pthread_exit() 函数设置的返回值。

一个线程运行结束后,结束信息保存在内核中,其他线程可以引用此线程的结束信息。

Linux系统中用函数 pthread_join(pthread_t tid, void **rval_ptr) 函数访问指定线程的结束信息。

头文件:  #include <pthread.h> 

参数:    第一个参数tid为需要取得结束线程的标识符,第二个参数rval_ptr为一个用户定义的指针,它可以用来存储被等待线程的返回值。这里需要注意的是,如果该线程正在运行中, pthread_join() 函数会导致线程阻塞,直到执行的线程结束为止。如果指定线程的线程ID和调用线程不属于同一个进程会出错,这也是线程的一个特点,同一进程下的线程共享资源,通信很简单,但是不同进程下的线程不共享资源,通信就没那么方便。

功能:    该函数取得一个执行完成的进程的退出信息,然后存在一个指针中,该指针指向存储线程返回信息的指针的首地址。

返回值:如果成功得到指定线程的退出信息返回0,失败返回错误号。

示例程序: pthread_exit() 函数和 pthread_join() 函数配合使用

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
/* 第一个线程,线程体函数返回 */
void * tfn1(void * arg)
{
       printf("the first\n");
       return (void *)1;    
}
/* 第二个线程,调用pthread_exit函数退出 */
void * tfn2(void * arg)
{
       printf("the second\n");
       pthread_exit((void *) 3);             
       printf("should not be here\n");
}
/* 第三个线程,休眠5秒钟后退出 */
void *tfn3(void *arg)
{
       printf("the third, sleep 10 secconds\n");
       sleep(5); /* 休眠5秒钟 */
       return NULL;
}
int main(void)
{
       pthread_t tid1, tid2, tid3;
       void * res; /* 指向线程的退出信息指针 */
       int err;
       /* 第一个线程的操作 */
       err = pthread_create(&tid1, NULL, tfn1, NULL); /* 创建第一个线程 */
       if(err != 0){
              printf("can’t create thread %d\n", strerror(err));
              exit(1);    
       }
       err = pthread_join(tid1, &res); /* 得到线程退出信息——tfn1函数的返回值 */
       if(err != 0){
              printf("can‘t join thread %d\n", strerror(err));
              exit(1);    
       }
       printf("result from thd1: %d\n", (unsigned int)(res)); /* 输出提示信息 */
       /* 第二个线程的操作 */
       err = pthread_create(&tid2, NULL, tfn2, NULL); /* 创建第二个线程 */
       if(err != 0){
              printf("can’t create thread %d\n", strerror(err));
              exit(1);    
       }
       err = pthread_join(tid2, &res); /* 得到线程的退出信息——pthread_exit函数
                                                               的参数所设置的值 */
       if(err != 0){
              printf("can’t join thread %d\n", strerror(err));
              exit(1);    
       }
       printf("result from thd2: %d\n", (unsigned int)(res));
       /* 第三个线程的操作 */
       err = pthread_create(&tid3, NULL, tfn3, NULL); /* 创建第三个线程 */
       if(err != 0){
              printf("can’t create thread %d\n", strerror(err));
              exit(1);
       }
       err = pthread_join(tid3, NULL); /* 不关心退出信息,只等待第三个线程退出 */
       if(err != 0){
              printf("can’t join thread %d\n", strerror(err));
              exit(1);
       }
       printf("the third thread has done\n");
       return 0;
}

从上边的程序可以看出,这3个线程是串行的,而线程的特点是并行性高,不符合一般的使用习惯,该程序只是为了演示好 pthread_exit() 函数和 pthread_join() 函数的用法,如果实际应用可以采用下边的编程模式:

pthread_create(……);            //创建第1个线程
pthread_create(……);            //创建第2个线程
pthread_create(……);            //创建第3个线程
pthread_join(tid1, &res);      //得到第1个线程的退出信息
pthread_join(tid2, &res);      //得到第2个线程的退出信息
pthread_join(tid3, &res);      //得到第3个线程的退出信息

 

线程学习笔记(二)