在 pthread_create 中创建的函数接受指向 int 的指针时的奇怪行为

Strange behavior when functions created in pthread_create accept pointer-to-int

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

void *runner(void * p)
{
    int *line = p;
    printf("line: %d\n", *line);
}
int main()
{
    pthread_t tid[2];                                                                                                       
    for (int i = 0; i < 2; i++)
        pthread_create(&tid[i], 0, runner, &i);
    for (int i = 0; i < 2; i++)                                                                                                       
        pthread_join(tid[i], NULL);
    return 0;
}

对于上面的代码,我希望输出为

line 0
line 1

但输出实际上是

line 1
line 2

那么这段代码有什么问题呢? i 是如何递增的?我必须将 structs 传递给 runner 函数吗?

无法保证 printf("line: %d\n", *line); 行会在 pthread_create returns 之前完成,这意味着您在 i 上有一场比赛。 (主线程尝试增加它,新线程尝试读取它 通过他们的参数指针)。

您可以通过传递指向不同对象的指针来解决问题(每个线程一个,最佳缓存对齐,但这在这里并不重要):

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

void *runner(void * p)
{
    int *line = p;
    printf("line: %d\n", *line);
    return 0;
}
int main()
{
    pthread_t tid[2];
    int ints[2];
    for (int i = 0; i < 2; i++){
        ints[i]=i;
        if(pthread_create(&tid[i], 0, runner, &ints[i])) return 1;
    }
    for (int i = 0; i < 2; i++)
        pthread_join(tid[i], NULL);
    return 0;
}

或按值传递 i(将其转换为 void*):

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

void *runner(void * p)
{
    printf("line: %d\n", (int)(intptr_t)p);
    return 0;
}
int main()
{
    pthread_t tid[2];
    int ints[2];
    for (int i = 0; i < 2; i++){
        if(pthread_create(&tid[i], 0, runner, (void*)(intptr_t)i)) return 1;
    }
    for (int i = 0; i < 2; i++)
        pthread_join(tid[i], NULL);
    return 0;
}