如果需要只终止某个线程而不终止整个进程,可以有三种方法:
1. 从线程函数 return。这种方法对主控线程不适用,因为从 main() 函数 return 相当于调用
exit()。
2. 线程可以调用 pthread_exit() 终止自己。其实这种方法和第1种方法类似。
3. 一个线程可以调用 pthread_cancel() 终止同一进程中的另一个线程。
注意:
同一进程的线程间,pthread_cancel 向另一线程发终止信号,系统并不会马上关闭被取消线程,只有在被取消线程
下次系统调用时,才会真正结束线程。或者调用pthread_testcancel,让内核去检测是否需要取消当前线程。
函数说明
#include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); 参数说明: thread:线程标识符,或者叫线程id; attr:线程属性设置; start_routine:线程函数的起始地址; arg:传递给 start_routine 的参数。 返回值: 成功:0 失败:-1 void pthread_exit(void *retval); 参数说明: retval:传出参数,可由其他函数如 pthread_join() 来检索获取。retval 所指内容应当是全局的或者是用 malloc 分配的。 int pthread_join(pthread_t thread, void **retval); 函数背景: 由于一个进程中的多个线程是共享数据段的,因此通常在线程退出之后,退出线程所占用的资源并不会随着线程的终止而得到释放。正如进程之间可以用wait()系统调用来同步终止并释放资源一样,线程之间也有类似机制,那就是pthread_j oin()函数。pthread_j oin 可以用于将当前线程挂起,等待线程的结束。这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源就被收回。 参数说明: thread:被等待线程(或者说被回收线程)的线程标识符; retval:用户定义的指针,用来存储被等待线程的返回值(不为NULL时)。 返回值: 成功:0 出错:-1
代码示例
#include <stdio.h> #include <stdlib.h> #include <pthread.h> void *doit1(void *); void *doit2(void *); int main() { pthread_t tid1, tid2; pthread_create(&tid1, NULL, doit1, NULL); pthread_create(&tid2, NULL, doit2, NULL); int *recv = NULL; printf("main(), &recv = %p, recv = %p\n", &recv, recv); // pthread_join() 是阻塞函数,它会一直等到被等待线程结束时才返回,而当 pthread_join() 返回时,被等待线程的资源就会被回收。 // 如果对被等待线程的终止状态不感兴趣,可以传NULL给 pthread_join() 的第二个参数。 printf("pthread1 join\n"); pthread_join(tid1, (void **)&recv); // recv 所指向的内存是全局的或者是在 pthread_join() 中分配好的。 printf("main(), &recv = %p, recv = %p, *recv = %d\n", &recv, recv, *recv); printf("pthread2 join\n"); pthread_join(tid2, NULL); // 若其他线程没有结束,则主控线程退出时不能采用 return 或 exit 方法。 printf("main will return\n"); return 0; } void *doit1(void *vptr) { int i; int *recv = NULL; for (i = 0; i < 10; i++) { printf("pthread1 working on, i = %d!\n", i); sleep(1); if (i == 3) { int *send = (int *)malloc(sizeof(int)); *send = 15; recv = send; printf("pthread1, &send = %p, send = %p, *send = %d\n", &send, send, *send); printf("pthread1 will call exit\n"); // 需要注意,pthread_exit() 或者 return 返回的指针所指向的内存单元必须是全局的或者是用 malloc() 分配的,不能在线程函数的栈上分配,因为当其它线程得到这个返回指针时线程函数已经退出了。 // pthread_exit() 调用后 ,该线程将直接退出,pthread_exit() 后面的方法都不再执行了。 pthread_exit(send); //break; // 在线程里调用 exit 会导致进程退出 //exit(1); printf("pthread1 finish call exit\n"); } } printf("pthread1 will return\n"); return recv; } void *doit2(void *vptr) { int i; for (i = 0; i < 10; i++) { printf("pthread2 working on, i = %d!\n", i); sleep(1); } return NULL; }
编译/执行
xj@ubuntu-server
:~/pthread_stop$ gcc main.c -lpthread
xj@ubuntu-server :~/pthread_stop$ ./a.out
pthread1 working on, i = 0!
main(), &recv = 0x7ffd022bb5a8, recv = (nil)
pthread1 join
xj@ubuntu-server :~/pthread_stop$ ./a.out
pthread1 working on, i = 0!
main(), &recv = 0x7ffd022bb5a8, recv = (nil)
pthread1 join
pthread2 working on, i = 0!
pthread1 working on, i = 1!
pthread2 working on, i = 1!
pthread2 working on, i = 2!
pthread1 working on, i = 2!
pthread2 working on, i = 3!
pthread1 working on, i = 3!
pthread2 working on, i = 4!
pthread1, &send = 0x7f5364030f00, send = 0x7f535c0008c0, *send = 15
pthread1 will call exit
main(), &recv = 0x7ffd022bb5a8, recv = 0x7f535c0008c0, *recv = 15
pthread2 join
pthread2 working on, i = 5!
pthread2 working on, i = 6!
pthread2 working on, i = 7!
pthread2 working on, i = 8!
pthread2 working on, i = 9!
main will return
pthread1 working on, i = 1!
pthread2 working on, i = 1!
pthread2 working on, i = 2!
pthread1 working on, i = 2!
pthread2 working on, i = 3!
pthread1 working on, i = 3!
pthread2 working on, i = 4!
pthread1, &send = 0x7f5364030f00, send = 0x7f535c0008c0, *send = 15
pthread1 will call exit
main(), &recv = 0x7ffd022bb5a8, recv = 0x7f535c0008c0, *recv = 15
pthread2 join
pthread2 working on, i = 5!
pthread2 working on, i = 6!
pthread2 working on, i = 7!
pthread2 working on, i = 8!
pthread2 working on, i = 9!
main will return