C中的多线程:传递结构

C中的多线程:传递结构,c,multithreading,pointers,C,Multithreading,Pointers,我正在学习C语言中的多线程性能。当我试图编写示例代码时,遇到了一个问题: #include <stdio.h> #include <string.h> #include <pthread.h> #include <stdlib.h> typedef struct{ int a; char b; } args; void* some_func (void* arg) { args *argsa = malloc(s

我正在学习C语言中的多线程性能。当我试图编写示例代码时,遇到了一个问题:

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

typedef struct{
    int a;
    char b;
    } args;

void* some_func (void* arg)
{
    args *argsa = malloc(sizeof(args));
//copy the content of arg to argsa, 
//so changes to arg in main would not affect argsa
    *argsa = *(args*) arg; 
    int i = 10;
    for (; i > 0; i--)
    {
        usleep (1); //to give other threads chances to cut in
        printf ("This is from the thread %d\n", argsa->a);
    }
    free (argsa);
}
int main()

{
    pthread_t thread[3];
    args ss;
    int index = 0;
    ss.b = 's';
    for (; index <3 ; index++)
    {
        ss.a = index;
        if (pthread_create (thread+index, NULL, some_func, (void*)&ss ))
        {
            usleep(10);
            printf ("something is wrong creating the thread"); 
        }
    }
        pthread_join ( thread[0], NULL);
        pthread_join ( thread[1], NULL);
        pthread_join ( thread[2], NULL);
    return 0;
}
但我找不到一种方法来解决这个问题,并获得所需的输出


任何帮助都将不胜感激

因为您正在向所有线程传递相同的指针。当线程0启动时,您已经将ss.a的值增加到1(然后是2)

这更正确一点:

void* some_func (void* arg)
{
    args *argsa = (args*)arg;
    int i;
    for (i = 0; i < 10; i++)
    {
        usleep (1); //to give other threads chances to cut in
        printf ("This is from the thread %d\n", argsa->a);
    }
}
int main()
{
    pthread_t thread[3];
    args ss[3];
    int index;
    for (index = 0; index < 3; index++)
    {
        ss[index].a = index;

        if (pthread_create(&thread[index], NULL, some_func, &ss[index] ))
        {
            printf ("something is wrong creating the thread"); 
        }
    }
    pthread_join ( thread[0], NULL);
    pthread_join ( thread[1], NULL);
    pthread_join ( thread[2], NULL);
    return 0;
}
void*some_func(void*arg)
{
args*argsa=(args*)arg;
int i;
对于(i=0;i<10;i++)
{
usleep(1);//给其他线程切入的机会
printf(“这来自线程%d\n”,argsa->a);
}
}
int main()
{
pthread_t thread[3];
args-ss[3];
整数指数;
对于(索引=0;索引<3;索引++)
{
ss[index].a=index;
if(pthread_create(&thread[index],NULL,some_func,&ss[index]))
{
printf(“创建线程时出错”);
}
}
pthread_join(线程[0],NULL);
pthread_join(线程[1],NULL);
pthread_join(线程[2],NULL);
返回0;
}

用于解决此类问题的模式如下:

  • 创建一个包含要传递给线程的参数的结构

  • 使用
    malloc
    分配这样的结构

  • 填充结构

  • 将指向结构的指针传递给线程

  • 当线程完成结构时,线程将释放它

  • 这假设您不需要从线程获取任何信息。如果这样做,您可以更改它,以便连接线程的代码释放结构。这也允许结构保存回复——加入线程,读取响应信息,然后释放结构


    不需要特殊的锁定或同步,因为虽然新创建的线程存在,但它是唯一接触该结构的线程。

    抱歉,伙计们,但我试图解决相同的问题,我认为还没有给出解决问题的正确答案。我自己尝试了这个,我得到了以下代码。现在,我编译并运行了它,它像我预期的那样工作得很好,但我仍然不太相信“主进程中的锁定和子进程中的解锁”是最优雅的解决方案,所以我想知道您对它的看法。事先非常感谢您的澄清

    代码如下:

    #include <stdio.h>
    #include <string.h>
    #include <pthread.h>
    #include <stdlib.h>
    
    typedef struct{
        int a;
        char b;
        } args;
    
    pthread_mutex_t lock;
    
    void* some_func (void *arg) {
        args argsa = *(args*)arg;
        pthread_mutex_unlock(&lock);
        printf ("This is from the thread %d\n", argsa.a);
    }
    
    int main() {
        pthread_t thread[10];
        args ss;
        int i, index=0;
        ss.b = 's';
    
        if (pthread_mutex_init(&lock, NULL) != 0) {
            printf("\n mutex init failed\n");
            return 1;
        }
    
        for (index = 0; index < 10 ; index++)
        {
            pthread_mutex_lock(&lock);
            ss.a = index;
            printf("index=%d, ", ss.a);
            if (pthread_create (thread+index, NULL, some_func, (void*)&ss ))
            {
                usleep(10);
                printf ("something is wrong creating the thread"); 
            }
        }
        for(i=0;i<10;i++)
            pthread_join ( thread[0], NULL);
        return 0;
    }
    

    这是一个糟糕的解决方案。malloc已经被使用了,大概是为了复制参数,为什么还要继续复制其他线程也在使用的引用呢?你说得对。但解决数据拷贝并不是我试图为他解决的问题。一个真正正确的解决方案是让主线程“等待”每个线程在继续之前复制数据。(等待复制数据的sleep语句不正确)。您需要一种适当的信号技术(超出了问题的范围)。但由于pthread_join是在main内部调用的,因此可以保证在线程退出之前ss[index]的生存期不会从堆栈中消失。所以以上的解决方案是安全的,只要args没有从堆栈上掉下来。对不起,我错过了你的主要阵列,那更好汉克斯,塞尔比。这很有效。但正如您所提到的,它实际上并没有解决数据复制问题,因为必须创建多个结构。正确的方法是什么?对不起,我不知道。正确诊断这个问题需要+1。每个线程具有单独结构的解决方案是正确的,并且在没有线程同步功能的情况下工作。如果必须使用单个结构,则解决方案将确保创建的线程和主线程对数据结构具有互斥访问权限。这与问题无关,但用于改进代码:为什么要将结构作为
    void*
    而不是
    args*
    传递?为什么要在堆上分配
    argsa
    ,而不仅仅是在堆栈上?@Matt是的,我可以将其作为
    args*
    传递——我只是看不到区别。我在堆上分配了
    argsa
    ,以避免可能更改“ss”。i、 e.如果
    args*argsa=malloc(sizeof(args))*argsa=*(args*)arg变为
    args*argsa=(args*)arg
    ,当主线程中的
    arg->a
    从0变为1时,第一个线程中的
    argsa->a
    会变为1吗?要在堆栈上分配
    argsa
    ,您将得到以下结果:
    args argsa=*(args*)arg arg仍将以相同的方式复制所有结构。注意:您必须使用
    args.a
    访问
    argsa
    的成员,而不是
    argsa->a
    。使用
    args*
    而不是
    void*
    的原因是为了清楚地表明您正在传递
    args*
    ,以便更好地保护类型安全,并避免必须将指针投射到
    void*
    并返回。@Matt
    pthread\u create
    要求函数采用
    void*
    参数。@Dave哦,对了,我忘了。
    #include <stdio.h>
    #include <string.h>
    #include <pthread.h>
    #include <stdlib.h>
    
    typedef struct{
        int a;
        char b;
        } args;
    
    pthread_mutex_t lock;
    
    void* some_func (void *arg) {
        args argsa = *(args*)arg;
        pthread_mutex_unlock(&lock);
        printf ("This is from the thread %d\n", argsa.a);
    }
    
    int main() {
        pthread_t thread[10];
        args ss;
        int i, index=0;
        ss.b = 's';
    
        if (pthread_mutex_init(&lock, NULL) != 0) {
            printf("\n mutex init failed\n");
            return 1;
        }
    
        for (index = 0; index < 10 ; index++)
        {
            pthread_mutex_lock(&lock);
            ss.a = index;
            printf("index=%d, ", ss.a);
            if (pthread_create (thread+index, NULL, some_func, (void*)&ss ))
            {
                usleep(10);
                printf ("something is wrong creating the thread"); 
            }
        }
        for(i=0;i<10;i++)
            pthread_join ( thread[0], NULL);
        return 0;
    }
    
    #./program
    index=0, This is from the thread 0
    index=1, This is from the thread 1
    index=2, This is from the thread 2
    index=3, This is from the thread 3
    index=4, This is from the thread 4
    index=5, This is from the thread 5
    index=6, This is from the thread 6
    index=7, This is from the thread 7
    index=8, This is from the thread 8
    index=9, This is from the thread 9