linux多线程参数的传递

文章通过一个C++多线程的例子,展示了如何使用pthread_create创建线程并传递参数。由于原始代码中线程函数输出的编号始终为5,作者分析了原因并提出了解决方案,即通过强制类型转换将整数变量var作为参数传递给线程函数,确保每个线程得到正确的编号。修改后的代码成功实现了每个线程打印出其创建时的正确编号,展示了线程参数传递的正确方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以下内容全部来自于b站码农论坛的个人空间_哔哩哔哩_bilibili

这位大哥是一位顶级大佬,有兴趣学c++的都可以去看一下他的视频。并且他还开源了他自己的框架,非常好用。 

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>

// 与客户端通信的主函数
void *mainfunc1(void *arg);
void *mainfunc2(void *arg);
void *mainfunc3(void *arg);
void *mainfunc4(void *arg);
void *mainfunc5(void *arg);
int var = 1;
int main()
{
    pthread_t pthid1, pthid2, pthid3, pthid4, pthid5;

    // 创建一个线程
    if (pthread_create(&pthid1, NULL, mainfunc1, NULL)!= 0)
    {
        printf("线程创建失败,程序退出。\n");
        return -1;
    }
    var++;
    if (pthread_create(&pthid2, NULL, mainfunc2, NULL)!= 0)
    {
        printf("线程创建失败,程序退出。\n");
        return -1;
    }
    var++;
    if (pthread_create(&pthid3, NULL, mainfunc3, NULL)!= 0)
    {
        printf("线程创建失败,程序退出。\n");
        return -1;
    }
    var++;
    if (pthread_create(&pthid4, NULL, mainfunc4, NULL)!= 0)
    {
        printf("线程创建失败,程序退出。\n");
        return -1;
    }
    var++;
    if (pthread_create(&pthid5, NULL, mainfunc5, NULL)!= 0)
    {
        printf("线程创建失败,程序退出。\n");
        return -1;
    }
    printf("pthid1=%lu\n", pthid1);
    printf("pthid2=%lu\n", pthid2);
    printf("pthid3=%lu\n", pthid3);
    printf("pthid4=%lu\n", pthid4);
    printf("pthid5=%lu\n", pthid5);

    printf("等待子线程退出。\n");
    pthread_join(pthid1, NULL);
    printf("子线程1已退出。\n");

    pthread_join(pthid2, NULL);
    printf("子线程2已退出。\n");

    pthread_join(pthid3, NULL);
    printf("子线程3已退出。\n");

    pthread_join(pthid4, NULL);
    printf("子线程4已退出。\n");

    pthread_join(pthid5, NULL);
    printf("子线程5已退出。\n");
    return 0;
}

void *mainfunc1(void *arg)
{
    printf("我是%d线程\n",var);
    for (int ii = 0;  ii < 10; ++ii)
    {
        // a++;
         sleep(1);
        // printf("a = %d func1 sleep lsec ok.\n", a);
    }
    pthread_exit(0);    // 子线程退出,不影响主线程
}

void *mainfunc2(void *arg)
{
    printf("我是%d线程\n", var);
    for (int ii = 0;  ii < 10; ++ii)
    {
        // a++;
        sleep(1);
        // printf("a = %d func2 sleep lsec ok.\n", a);
    }
    pthread_exit(0);    // 子线程退出,不影响主线程
}

void *mainfunc3(void *arg)
{
    printf("我是%d线程\n", var);
    for (int ii = 0;  ii < 10; ++ii)
    {
        // a++;
        sleep(1);
        // printf("a = %d func3 sleep lsec ok.\n", a);
    }
    pthread_exit(0);    // 子线程退出,不影响主线程
}

void *mainfunc4(void *arg)
{
    printf("我是%d线程\n", var);
    for (int ii = 0;  ii < 10; ++ii)
    {
        // a++;
        sleep(1);
        // printf("a = %d func4 sleep lsec ok.\n", a);
    }
    pthread_exit(0);    // 子线程退出,不影响主线程
}

void *mainfunc5(void *arg)
{
    printf("我是%d线程\n", var);
    for (int ii = 0;  ii < 10; ++ii)
    {
        // a++;
        sleep(1);
        // printf("a = %d func5 sleep lsec ok.\n", a);
    }
    pthread_exit(0);    // 子线程退出,不影响主线程
}

这个代码就是创建线程,然后在每个函数中输出自己是第几个线程,按照这个代码来说我们输出的结果应该是一 一对应的。我们来看一下结果。

结果都是5,这里出现这种结果的原因就是你创建线程是按照顺序创建的,但是你的mainfunc()函数不一定是创建一个就输出一个,所以都是等主线程都执行完毕了,var这个时候已经等于5了,所以你最后输出的结果那肯定都是5。那么现在就来解决这个问题。 

 我们通过man pthread_create 可以看到这个函数的第四个参数是一个void *类型,这里引入一个强制类型转换的概念。

通常指针都是存地址,但是我这里我想传值进去,因为如果传地址那不就是和前面的全局变量没有什么区别了,所以这里我们要传值进去,就得强制类型转化一下。下面的这种强制类型转化很明显不可以,我们来看下报了什么错误

 我们先看第一个报错,告诉我们大小不同,我们知道不同操作系统下的指针大小是不一样的,64位下8字节。所以我们改一下。

 损失精度好办。

 ok,这样我们就解决了如何传值的问题了。那么回到一开始的传参,我们修改一下。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>

// 与客户端通信的主函数
void *mainfunc1(void *arg);
void *mainfunc2(void *arg);
void *mainfunc3(void *arg);
void *mainfunc4(void *arg);
void *mainfunc5(void *arg);

int main()
{
    /*
    // 不一样的强制类型转换
    int ii = 10;
    void *ptr1 = (void *)(long)ii;
    int jj = (int)(long)ptr1;

    long aa = 10;
    void *ptr2 = (void *)aa;
    long bb = (long)ptr2;
    */

    int var = 1;
    pthread_t pthid1, pthid2, pthid3, pthid4, pthid5;

    // 创建一个线程
    // pthread_create()第四个参数是void *,所以需要强制转化
    if (pthread_create(&pthid1, NULL, mainfunc1, (void *)(long)var)!= 0)
    {
        printf("线程创建失败,程序退出。\n");
        return -1;
    }
    var++;
    if (pthread_create(&pthid2, NULL, mainfunc2, (void *)(long)var)!= 0)
    {
        printf("线程创建失败,程序退出。\n");
        return -1;
    }
    var++;
    if (pthread_create(&pthid3, NULL, mainfunc3, (void *)(long)var)!= 0)
    {
        printf("线程创建失败,程序退出。\n");
        return -1;
    }
    var++;
    if (pthread_create(&pthid4, NULL, mainfunc4, (void *)(long)var)!= 0)
    {
        printf("线程创建失败,程序退出。\n");
        return -1;
    }
    var++;
    if (pthread_create(&pthid5, NULL, mainfunc5, (void *)(long)var)!= 0)
    {
        printf("线程创建失败,程序退出。\n");
        return -1;
    }
    printf("pthid1=%lu\n", pthid1);
    printf("pthid2=%lu\n", pthid2);
    printf("pthid3=%lu\n", pthid3);
    printf("pthid4=%lu\n", pthid4);
    printf("pthid5=%lu\n", pthid5);

    printf("等待子线程退出。\n");
    pthread_join(pthid1, NULL);
    printf("子线程1已退出。\n");

    pthread_join(pthid2, NULL);
    printf("子线程2已退出。\n");

    pthread_join(pthid3, NULL);
    printf("子线程3已退出。\n");

    pthread_join(pthid4, NULL);
    printf("子线程4已退出。\n");

    pthread_join(pthid5, NULL);
    printf("子线程5已退出。\n");
    return 0;
}

void *mainfunc1(void *arg)
{
    printf("我是%d线程\n", (int)(long)arg);
    for (int ii = 0;  ii < 10; ++ii)
    {
        // a++;
         sleep(1);
        // printf("a = %d func1 sleep lsec ok.\n", a);
    }
    pthread_exit(0);    // 子线程退出,不影响主线程
}

void *mainfunc2(void *arg)
{
    printf("我是%d线程\n",(int)(long)arg);
    for (int ii = 0;  ii < 10; ++ii)
    {
        // a++;
        sleep(1);
        // printf("a = %d func2 sleep lsec ok.\n", a);
    }
}

void *mainfunc3(void *arg)
{
    printf("我是%d线程\n", (int)(long)arg);
    for (int ii = 0;  ii < 10; ++ii)
    {
        // a++;
        sleep(1);
        // printf("a = %d func3 sleep lsec ok.\n", a);
    }
}

void *mainfunc4(void *arg)
{
    printf("我是%d线程\n", (int)(long)arg);
    for (int ii = 0;  ii < 10; ++ii)
    {
        // a++;
        sleep(1);
        // printf("a = %d func4 sleep lsec ok.\n", a);
    }
}

void *mainfunc5(void *arg)
{
    printf("我是%d线程\n", (int)(long)arg);
    for (int ii = 0;  ii < 10; ++ii)
    {
        // a++;
        sleep(1);
        // printf("a = %d func5 sleep lsec ok.\n", a);
    }
}

 再来看一下结果。

 这样就都分开了,顺序不一样是正常的,因为编译器的优化问题,所以顺序不一样很正常,我们只需要知道结果是每一个线程都知道了自己准确的编号了。

还有一个解决方案那就是在每一个var++前面sleep(1);但是这样会耗时间。

总结,主要是说一下pthread_create()函数的参数传递。 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值