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