Странное поведение, когда функции, созданные в pthread_create, принимают указатель на int - PullRequest
0 голосов
/ 24 марта 2020
#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 увеличился? Должен ли я передавать struct s в функцию бегуна?

1 Ответ

1 голос
/ 24 марта 2020

Нет никакой гарантии, что линия printf("line: %d\n", *line); завершится sh до того, как pthread_create вернется, что означает, что у вас есть гонка на 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...