为什么我不能将 "for" 索引直接传递给 pthread_create 调用?

Why can't I pass my "for" index directly to a pthread_create call?

#define THREADS_NUMBER 10

给定函数 f:

void *f(void *arg){

    pthread_mutex_lock(&mutex);
    printf("%i\n", *((int*) arg);
    pthread_mutex_unlock(&mutex);

}

我不明白为什么要写这个:

pthread_t threads[THREADS_NUMBER];
for(int i = 0; i < THREADS_NUMBER; i++){
    pthread_create(&threads[i], NULL, f, &i);
}
for(int i = 0; i < THREADS_NUMBER; i++){
    pthread_join(threads[i], NULL);
}

输出这个:

2 4 4 5 5 6 8 8 9 10

写这篇文章时:

int t[10];
for(int i = 0; i < 10; i++)
    t[i] = i;
pthread_t threads[THREADS_NUMBER];
for(int i = 0; i < THREADS_NUMBER; i++){
    pthread_create(&threads[i], NULL, f, &t[i]);
}
for(int i = 0; i < THREADS_NUMBER; i++){
    pthread_join(threads[i], NULL);
}

输出这个:

0 1 4 3 5 2 6 7 9 8

(如果您没有注意到差异,它是在 pthread_create 调用中传递给线程函数 f 的参数。)

因为这里:

int i;
...
     pthread_create(&threads[i], NULL, f, &i);

您将指向内存地址的指针传递给您的线程:

void *f(void *arg){

但是当线程执行的时候,main线程已经再次修改了这个值! 所以你必须传递这个值的副本,就像你对你的数组所做的那样,或者像这样:

for(int i = 0; i < THREADS_NUMBER; i++){
    int *arg = malloc(sizeof(int));
    *arg = i;
    pthread_create(&threads[i], NULL, f, arg);
}

记得在线程函数 (f) 中释放不再需要的值 — 必须避免内存泄漏,因为没有其他引用指向已分配的 space。因此,使用数组的解决方案可能更好。

尝试展开循环。两种情况会变成下图

第一种情况:

pthread_create(&threads[0], NULL, f, &i);
pthread_create(&threads[1], NULL, f, &i);

…
pthread_create(&threads[9], NULL, f, &i);

第二种情况:

pthread_create(&threads[0], NULL, f, &t[0]);
pthread_create(&threads[0], NULL, f, &t[1]);
…
pthread_create(&threads[9], NULL, f, &t[9]);

如果您注意到,在第一种情况下,您总是将 &i 传递给每个线程,因此每个线程都将指向相同的 i 及其最新内容。