• 线程学习笔记(二)


    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个线程的退出信息
  • 相关阅读:
    sql性能查询
    ASP.Net Web应用程序与EXCEL交互时遇到的权限问题
    Connection strings for Excel 2007
    获取异常的具体出处dbms_utility.format_error_backtrace
    C#获取Excel架构信息的方法
    Oracle强杀进程
    C#游标溢出(访问数据库)解决方案。
    Visual C# 2008 调试技巧一
    【POI】修改Excel内容
    【Eclipse】在Eclipse工具中自定义类注释
  • 原文地址:https://www.cnblogs.com/Mr--Yang/p/6287719.html
Copyright © 2020-2023  润新知