线程终止方式

如果需要只终止某个线程而不终止整个进程,可以有三种方法:
    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
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

猜你喜欢

转载自blog.csdn.net/u011362297/article/details/49679497