• 第三章 LInux多线程开发 3.1-3.5线程创建 终止 分离


    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    创建线程:(好好记住 可能会叫写代码)

    一般情况下,main函数所在的线程我们称之为主线程(main线程),其余创建的线程称之为子线程。 程序中默认只有一个进程,fork()函数调用,2进行
    程序中默认只有一个线程,pthread_create()函数调用,2个线程。

    #include
    int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
    void *(*start_routine) (void *), void *arg);

        - 功能:创建一个子线程
        - 参数:
            - thread:传出参数,线程创建成功后,子线程的线程ID被写到该变量中。
            - attr : 设置线程的属性,一般使用默认值,NULL
            - start_routine : 函数指针,这个函数是子线程需要处理的逻辑代码
            - arg : 给第三个参数使用,传参
        - 返回值:
            成功:0
            失败:返回错误号。这个错误号和之前errno不太一样。
            获取错误号的信息:  char * strerror(int errnum);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    #include 
    #include 
    #include 
    #include 
    
    void * callback(void * arg) {
        printf("child thread...\n");
        printf("arg value: %d\n", *(int *)arg);
        return NULL;
    }
    
    int main() {
    
        pthread_t tid;
    
        int num = 10;
    
        // 创建一个子线程
        int ret = pthread_create(&tid, NULL, callback, (void *)&num);
    
        if(ret != 0) {
            char * errstr = strerror(ret);
            printf("error : %s\n", errstr);
        } 
    
        for(int i = 0; i < 5; i++) {
            printf("%d\n", i);
        }
    
        sleep(1);
    
        return 0;   // exit(0);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    终止线程

    /*
    
        #include 
        void pthread_exit(void *retval);
            功能:终止一个线程,在哪个线程中调用,就表示终止哪个线程
            参数:
                retval:需要传递一个指针,作为一个返回值,可以在pthread_join()中获取到。
    
        pthread_t pthread_self(void);
            功能:获取当前的线程的线程ID
    
        int pthread_equal(pthread_t t1, pthread_t t2);
            功能:比较两个线程ID是否相等
            不同的操作系统,pthread_t类型的实现不一样,有的是无符号的长整型,有的
            是使用结构体去实现的。
    */
    #include 
    #include 
    #include 
    
    void * callback(void * arg) {
        printf("child thread id : %ld\n", pthread_self());
        return NULL;    // pthread_exit(NULL);
    } 
    
    int main() {
    
        // 创建一个子线程
        pthread_t tid;
        int ret = pthread_create(&tid, NULL, callback, NULL);
    
        if(ret != 0) {
            char * errstr = strerror(ret);
            printf("error : %s\n", errstr);
        }
    
        // 主线程
        for(int i = 0; i < 5; i++) {
            printf("%d\n", i);
        }
    
        printf("tid : %ld, main thread id : %ld\n", tid ,pthread_self());
    
        // 让主线程退出,当主线程退出时,不会影响其他正常运行的线程。
        pthread_exit(NULL);
    
        printf("main thread exit\n");
    
        return 0;   // exit(0);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    连接已终止的线程

    /*
        #include 
        int pthread_join(pthread_t thread, void **retval);
            - 功能:和一个已经终止的线程进行连接
                    回收子线程的资源
                    这个函数是阻塞函数,调用一次只能回收一个子线程
                    一般在主线程中使用
            - 参数:
                - thread:需要回收的子线程的ID
                - retval: 接收子线程退出时的返回值
            - 返回值:
                0 : 成功
                非0 : 失败,返回的错误号
    */
    
    #include 
    #include 
    #include 
    #include 
    
    int value = 10;
    
    void * callback(void * arg) {
        printf("child thread id : %ld\n", pthread_self());
        // sleep(3);
        // return NULL; 
        // int value = 10; // 局部变量
        pthread_exit((void *)&value);   // return (void *)&value;
    } 
    
    int main() {
    
        // 创建一个子线程
        pthread_t tid;
        int ret = pthread_create(&tid, NULL, callback, NULL);
    
        if(ret != 0) {
            char * errstr = strerror(ret);
            printf("error : %s\n", errstr);
        }
    
        // 主线程
        for(int i = 0; i < 5; i++) {
            printf("%d\n", i);
        }
    
        printf("tid : %ld, main thread id : %ld\n", tid ,pthread_self());
    
        // 主线程调用pthread_join()回收子线程的资源
        int * thread_retval;
        ret = pthread_join(tid, (void **)&thread_retval);
    
        if(ret != 0) {
            char * errstr = strerror(ret);
            printf("error : %s\n", errstr);
        }
    
        printf("exit data : %d\n", *thread_retval);
    
        printf("回收子线程资源成功!\n");
    
        // 让主线程退出,当主线程退出时,不会影响其他正常运行的线程。
        pthread_exit(NULL);
    
        return 0; 
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    线程的分离

    /*
        #include 
        int pthread_detach(pthread_t thread);
            - 功能:分离一个线程。被分离的线程在终止的时候,会自动释放资源返回给系统。
              1.不能多次分离,会产生不可预料的行为。
              2.不能去连接一个已经分离的线程,会报错。
            - 参数:需要分离的线程的ID
            - 返回值:
                成功:0
                失败:返回错误号
    */
    #include 
    #include 
    #include 
    #include 
    
    void * callback(void * arg) {
        printf("chid thread id : %ld\n", pthread_self());
        return NULL;
    }
    
    int main() {
    
        // 创建一个子线程
        pthread_t tid;
    
        int ret = pthread_create(&tid, NULL, callback, NULL);
        if(ret != 0) {
            char * errstr = strerror(ret);
            printf("error1 : %s\n", errstr);
        }
    
        // 输出主线程和子线程的id
        printf("tid : %ld, main thread id : %ld\n", tid, pthread_self());
    
        // 设置子线程分离,子线程分离后,子线程结束时对应的资源就不需要主线程释放
        ret = pthread_detach(tid);
        if(ret != 0) {
            char * errstr = strerror(ret);
            printf("error2 : %s\n", errstr);
        }
    
        // 设置分离后,对分离的子线程进行连接 pthread_join()
        // ret = pthread_join(tid, NULL);
        // if(ret != 0) {
        //     char * errstr = strerror(ret);
        //     printf("error3 : %s\n", errstr);
        // }
    
        pthread_exit(NULL);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
  • 相关阅读:
    论文笔记:Skeleton Key: Image Captioning by Skeleton-Attribute Decomposition
    叮当健康(9886.HK)赴港上市,“快+全”组合下继续保持行业领先
    DC-7靶机
    Go-函数作为参数传递
    【数据处理】Python:实现求条件分布函数 | 求平均值方差和协方差 | 求函数函数期望值的函数 | 概率论
    vpp hqos分析
    PCL库常用算法
    c++基础:指针
    ESP32C3基于Arduino框架下的 ESP32 RainMaker开发示例教程
    使用OneDNS完美解决办公网络优化问题
  • 原文地址:https://blog.csdn.net/weixin_46716100/article/details/132712933