单线程可以通过三种方式退出:
- 线程可以简单地从启动例程中返回,因此可以在不终止整个进程的情况下,停止他的控制流
- 线程可以被同一进程中的其他线程取消
- 线程调用pthread_exit
#include <pthread.h>
void pthread_exit(void *retval);
pthread_exit和return的区别:
- return 语句和 pthread_exit() 函数的含义不同,return 的含义是返回,它不仅可以用于线程执行的函数,普通函数也可以使用;pthread_exit() 函数的含义是线程退出,它专门用于结束某个线程的执行。
- return 语句不仅会终止主线程执行,还会终止其它子线程执行,pthread_exit() 函数只会终止当前线程,不会影响进程中其它线程的执行
- pthread_exit() 可以自动调用线程清理程序(本质是一个由 pthread_cleanup_push() 指定的自定义函数),return 则不具备这个能力
如果想获取某个线程执行结束时返回的数据,可以调用 pthread_join() 函数来实现。
#include <pthread.h>
int pthread_join(pthread_t thread, void ** retval);
//thread 参数用于指定接收哪个线程的返回值;retval 参数表示接收到的返回值,如果 thread 线程没有返回值,又或者我们不需要接收 thread 线程的返回值,可以将 retval 参数置为 NULL
pthread_join() 函数会一直阻塞调用它的线程,直至目标线程执行结束(接收到目标线程的返回值),阻塞状态才会解除。
代码实例:
#include "apue.h"
#include <pthread.h>
void* thr_fn1(void* arg)
{
printf("thread 1 returning\n");
return ((void*)1);
}
void* thr_fn2(void* arg)
{
printf("thread 2 returning\n");
pthread_exit ((void*)2);
}
int main()
{
int err;
pthread_t tid1,tid2;
void *tret;
err=pthread_create(&tid1,NULL,thr_fn1,NULL);
if(err!=0)
err_exit(err,"can not create thread 1");
err=pthread_create(&tid2,NULL,thr_fn2,NULL);
if(err!=0)
err_exit(err,"can not create thread 2");
err=pthread_join(tid1,&tret);
if(err!=0)
err_exit(err,"can not join thread 1");
printf("thread 1 exit code %ld\n",(long)tret);
err=pthread_join(tid2,&tret);
if(err!=0)
err_exit(err,"can not join thread 2");
printf("thread 2 exit code %ld\n",(long)tret);
exit(0);
}
线程可以通过调用pthread_cancel函数来请求取消同一进程中的其他线程
#include <pthread.h>
int pthread_cancel(pthread_t tid);
//返回值,若成功返回0,否则返回错误编号
注意pthread_cancel函数并不等待线程终止,它仅仅提出请求。
线程可以安排它退出时需要调用的函数,称为线程清理处理程序
#include <pthread.h>
void pthread_cleanup_push(void (*ttn)(void *),void* arg);
void pthread_cleanup_pop(int execute);
当线程执行以下动作的时候,清理函数rtn是由pthread_clean_push函数调度的,调用时只有一个参数arg:
- 调用pthread_exit时;
- 响应取消请求时
- 用非零execute参数调用pthread_cleanup_pop时