Почему я не могу передать свой индекс "for" напрямую в вызов pthread_create? - PullRequest
3 голосов
/ 11 октября 2019
#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

(Если вы не заметили разницу, это аргумент, переданный функции потока f в pthread_create Звоните.)

Ответы [ 2 ]

5 голосов
/ 11 октября 2019

Попробуйте развернуть петли. Два случая станут следующими:

первый случай:

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 и его последнее содержимое.

3 голосов
/ 11 октября 2019

Потому что здесь:

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), когда оно нетребуется дольше - необходимо избежать утечки памяти, потому что нет другой ссылки на выделенное пространство. Поэтому решение с использованием массива, вероятно, лучше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...