Linux线程的创建

Linux线程的创建

这里讲POSIX线程的Linux实现,使用的NPTL线程库

  1. 基本概念:

    1. 一个进程中至少含有一个主线程(这个是默认的,不需要程序员手动创建),同一个进程中可以创建多个子线程,这些子线程共享进程的地址空间
    2. 需要注意的是:进程之间创建者进程称为父进程,被创建的进程称为子进程;进程中默认的线程称为主线程,其它统称都叫子线程!
    3. 更详细的进程与线程的对比:https://blog.csdn.net/weixin_48617416/article/details/120346554
  2. 线程的创建

    #include <pthread.h>
    int pthread_create(pthread_t *thread, const pthread_attr_t *attr, 
    				   void *(*start_routine) (void *), void *arg);
    

    参数1:线程id,用于标识线程的

    参数2:线程的属性,一般默认为NULL

    参数3:函数指针,指向的是线程的处理函数

    参数4:线程处理函数的参数

    返回值:成功返回0, 失败返回错误码

  3. 线程的等待(回收子线程的资源)

    int pthread_join(pthread_t thread, void **retval);
    

    参数1:需要等待的子线程的线程id

    参数2:捕获子线程的退出码

    返回值:成功返回0, 失败返回错误码

    注意:同一进程内,主线程可以等待任意子线程,子线程之间除了主线程以外可以互相等待

  4. 线程的退出

    void pthread_exit(void *retval);
    

    参数:子线程的退出码

  5. 代码示例1(gcc编译的时候需要加 -pthread或者-lpthread)

    #include <stdio.h>
    #include <string.h>
    #include <pthread.h>
    
    void *threadFunc(void* p)
    {
        printf("child thread\n");
    
        //线程库的退出函数, 尽量不要使用return
        pthread_exit(NULL);
    }
    
    int main(int argc, char **argv)
    {
        int ret = 0;
        pthread_t thid;
    
        //创建线程, 成功返回0,失败返回错误码
        ret = pthread_create(&thid, NULL, threadFunc, NULL);
        if(0 != ret){
            printf("pthread_create: %s\n", strerror(ret));
        }
        
        printf("main thread\n");
    
        //线程等待函数, 回收线程的相关资源
        ret = pthread_join(thid, NULL);
        if(0 != ret){
            printf("pthread_join: %s\n", strerror(ret));
        }
    
        return 0;
    }
    
    gcc xx.c -pthread
    //运行结果:
    main thread
    child thread
    
  6. 代码示例2

    #include <stdio.h>
    #include <string.h>
    #include <pthread.h>
    
    void *threadFunc(void* p)
    {
        printf("child thread\n");
    
        //线程库的退出函数, 尽量不要使用return
        long val = 9;
        
        //子线程采用值传递方式退出栈空间val的值为9,
       	//需要注意这个值是long类型是最好的方式,64位系统中long和指针都占8位,
        //可以有效避免代码产生warning,
        //当然也可以传递堆空间等指针出去,但是需要注意的是
        //不太建议传递堆空间或者锁等指针出去,防止在其他线程内忘记回收堆空间或者忘记解锁等!
        pthread_exit((void*)val);
    }
    
    int main(int argc, char **argv)
    {
        int ret = 0;
        pthread_t thid;
    
        //创建线程, 成功返回0,失败返回错误码
        ret = pthread_create(&thid, NULL, threadFunc, NULL);
        if(0 != ret){
            printf("pthread_create: %s\n", strerror(ret));
        }
        
        printf("main thread\n");
    
        long retVal = 0;
        //线程等待函数, 回收线程的相关资源, 捕获子线程的退出码
        ret = pthread_join(thid, (void**)&retVal);
        if(0 != ret){
            printf("pthread_join: %s\n", strerror(ret));
        }
    
        printf("child thread exit val = %ld\n", retVal);
    
        return 0;
    }
    
    //运行结果
    main thread
    child thread
    child thread exit val = 9
    
  7. 代码示例3

    #include <stdio.h>
    #include <string.h>
    #include <pthread.h>
    
    void *threadFunc(void* p)
    {
        //接收主线程传过来的值
        long num = (long)p;
        printf("child num = %ld\n", num);
    
        //线程库的退出函数, 尽量不要使用return
        long val = 9;
    
        //子线程采用值传递方式退出栈空间val的值为9,
        //需要注意这个值是long类型是最好的方式,64位系统中long和指针都占8位,
        //可以有效避免代码产生warning,
        //当然也可以传递堆空间等指针出去,但是需要注意的是
        //不太建议传递堆空间或者锁等指针出去,防止在其他线程内忘记回收堆空间或者忘记解锁等!
        pthread_exit((void*)val);
    
    }
    
    int main(int argc, char **argv)
    {
        int ret = 0;
        pthread_t thid;
    
        long num = 2;
        //给子线程采用值传递的方式传递num
        ret = pthread_create(&thid, NULL, threadFunc, (void*)num);
        if(0 != ret){
            printf("pthread_create: %s\n", strerror(ret));
        }
    
        printf("main thread\n");
    
        long retVal = 0;
        //线程等待函数, 回收线程的相关资源, 捕获子线程的退出码
        ret = pthread_join(thid, (void**)&retVal);
        if(0 != ret){
            printf("pthread_join: %s\n", strerror(ret));
        }
    
        printf("child thread exit val = %ld\n", retVal);
    
        return 0;
    }
    
    //运行结果
    main thread
    child num = 2
    child thread exit val = 9
    
  8. 代码示例4

    #include <stdio.h>
    #include <string.h>
    #include <pthread.h>
    
    void *threadFunc(void* p)
    {
        printf("child thread\n");
    
        pthread_exit(NULL);
    }
    
    int main(int argc, char **argv)
    {
        int ret = 0;
        pthread_t thid1, thid2;
    
        //创建线程1
        ret = pthread_create(&thid1, NULL, threadFunc, NULL);
        if(0 != ret){
            printf("pthread_create1: %s\n", strerror(ret));
        }
    
        //创建线程2,需要注意哦,有靓仔看到这里写的是与上面同一个线程处理函数
        //就认为是一个线程。这里是两个线程哦,只不过线程的功能是一样的,
        //线程处理函数你可以理解就是线程的功能,很显然线程的功能可以相同!
        ret = pthread_create(&thid2, NULL, threadFunc, NULL);
        if(0 != ret){
            printf("pthread_create2: %s\n", strerror(ret));
        }
        printf("main thread\n");
    
        //注意,每一个线程都需要回收哦
        ret = pthread_join(thid1, NULL);
        if(0 != ret){
            printf("pthread_join1: %s\n", strerror(ret));
        }
    
        ret = pthread_join(thid2, NULL);
        if(0 != ret){
            printf("pthread_join2: %s\n", strerror(ret));
        }
    
        return 0;
    }
    //运行结果
    main thread
    child thread
    child thread
    
  9. 代码示例5

    #include <stdio.h>
    #include <string.h>
    #include <pthread.h>
    
    void *threadFunc(void* p)
    {
        //子线程接收主线程传递过来的值
        long num = (long)p;
        printf("child num = %ld\n", num);
    
        //修改num值,当成退出码传递出去给主线程
        num = 10;
        pthread_exit((void*)num);
    }
    
    int main(int argc, char **argv)
    {
        int ret = 0;
        pthread_t thid1, thid2;
    
        long num = 2;
        //创建线程1
        ret = pthread_create(&thid1, NULL, threadFunc, (void*)num);
        if(0 != ret){
            printf("pthread_create1: %s\n", strerror(ret));
        }
    
        num += 1;
    
        //创建线程2,需要注意哦,有靓仔看到这里写的是与上面同一个线程处理函数
        //就认为是一个线程。这里是两个线程哦,只不过线程的功能是一样的,
        //线程处理函数你可以理解就是线程的功能,很显然线程的功能可以相同!
        ret = pthread_create(&thid2, NULL, threadFunc, (void*)num);
        if(0 != ret){
            printf("pthread_create2: %s\n", strerror(ret));
        }
        printf("main thread\n");
    
        //注意,每一个线程都需要回收哦
        ret = pthread_join(thid1, NULL);
        if(0 != ret){
            printf("pthread_join1: %s\n", strerror(ret));
        }
    
        //接收子线程2的退出码
        long retVal = 0;
        ret = pthread_join(thid2, (void**)&retVal);
        if(0 != ret){
            printf("pthread_join2: %s\n", strerror(ret));
        }
    
        //通过这个打印你会清晰的看到这是值传递,子线程中的修改不会影响主线程的num值
        printf("main num = %ld, retVal = %ld\n", num, retVal);
    
        return 0;
    }
    
    //运行结果
    main thread
    child num = 3
    child num = 2
    main num = 3, retVal = 10
    

以上就是线程的一些基本使用方式,本人能力有限,如有错误望各位大佬不吝指正,原创不易,转载请注明出处!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值