【问题标题】:Arguments were passed wrong in pthread参数在 pthread 中传递错误
【发布时间】:2012-09-03 06:07:58
【问题描述】:

我编写了一个代码来打印字符串:“线程 0”到“线程 4”使用 pthread。

这是我的代码:

案例一:

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

void *print_message_function(void* parameter) {
    long *i = (long *)parameter;
    printf("Thread %ld\n", *i);
    pthread_exit(0);
}

int main(int argc, char *argv[]) {
    pthread_t threads[5];
    long i = 0;
    for (i = 0; i < 5; i++) {
        pthread_create(&threads[i], 0, print_message_function, (void *)&i);
    }
    
    pthread_exit(NULL);
}

但结果是:

Thread 2
Thread 3
Thread 3
Thread 4
Thread 5

或:

Thread 0
Thread 0
Thread 0
Thread 0
Thread 0

当我再次运行它时它改变了。所以我不知道为什么我传递的值是(2到5)或全部(0)或.....(很多情况下)。我认为我传递的参数是从 0 到 4。

案例 2:

当我更改为新代码时:

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

void *print_message_function(void *parameter);

int main(int argc, char *argv[]) {
    pthread_t threads[5];
    int i = 0;
    for (i = 0; i < 5; i++) {
        char *msg = (char*)malloc(sizeof(char));
        sprintf(msg, "Thread %d", i);
        pthread_create(&threads[i], 0, print_message_function, (void *)msg);
    }
}

void *print_message_function(void *parameter) {
    printf("%s\n", (char *)parameter);
}

结果是:

Thread 1
Thread 0
Thread 3
Thread 2
Thread 4
Thread 4

这意味着循环运行了 6 次!为什么?

【问题讨论】:

    标签: linux multithreading parameters pthreads arguments


    【解决方案1】:

    案例1改为:

    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    
    void *print_message_function(void* parameter) {
        long i = (long)parameter;  // <<<
        printf("Thread %ld\n", i); // <<<
        pthread_exit(0);
    }
    
    int main(int argc, char *argv[]) {
        pthread_t threads[5];
        long i = 0;
        for (i = 0; i < 5; i++) {
            pthread_create(&threads[i], 0, print_message_function, (void *)i); // <<<
        }
    
        pthread_exit(NULL);
    }
    

    您之前看到不一致结果的原因是因为您将一个指针传递给每个线程,其中每个指针都指向同一个局部变量,然后您正在对其进行修改。

    案例 2 中,您 mallocing 只输入一个字符,然后尝试向其写入字符串。应该很容易修复。

    【讨论】:

    • 啊,我明白了案例 1。你是对的! :)。但是在情况 2 中,为什么循环运行 6 次?
    • 万一 2 任何事情都可能发生,因为你在内存中跺脚。
    • 我想问你一个问题:如果我使用结构体而不是整数i,我不能通过:(void*)struct_param。我怎样才能解决这个问题?我不想传递它的地址。
    • 如果结构需要对每个线程都是唯一的,那么您将需要创建结构的 N 个实例,每个实例都有足够长的生命周期。您可能希望通过mallocing 每个结构来做到这一点,就像在 Case 2 中为每个字符串所做的那样。当线程终止时,您需要确保 free 每个结构。
    【解决方案2】:

    您的 case 2 方法是有效的,但是您需要修复 malloc 部分以分配足够的字节。改成

    char *msg = (char*)malloc(sizeof(char) * (strlen("Thread ") + 10));
    // assuming i will take at most 9-digits (unlikely case)
    

    对于您的案例 1,您传递的地址是 i。但是i 的值正在更改线程函数,当它尝试打印时,它将获取该位置的任何值。另请注意,i 的地址在线程函数执行时可能无效,因为它分配在堆栈上,并且会在main 函数返回时消失。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-09
      • 1970-01-01
      • 2013-12-10
      • 2014-12-18
      • 1970-01-01
      • 2015-10-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多