Как мне обеспечить, чтобы все потоки, созданные в функции, возвращались до того, как та же самая функция завершается? - PullRequest
2 голосов
/ 11 ноября 2019

Рассмотрим следующий раздел функции C :

for (int i = 0; i < n; ++i) {
    thread_arg *arg = (thread_arg *) malloc(sizeof(thread_arg));
    arg->random_value = random_value;
    arg->message = &(message[i * 10]);

    if (pthread_create(NULL, NULL, thread_start, (void *) &arg)) {
        perror("pthread_create");
        exit(EXIT_FAILURE);
    }
}

В этом цикле for я создаю n потоки, которые выполняют общую процедуру с различными параметрами. Этот цикл for является частью большой функции, которая возвращает структуру данных, которая изменяется всеми потоками параллельно. Таким образом, важно, чтобы эта большая функция не возвращалась до завершения всех потоков.
Я надеялся найти более простой способ, чем присвоение индивидуального идентификатора всем этим потокам и последующее объединение с pthread_join.
Есть ли общий подход к тому, чтобы сказать функции что-то вроде «эй, не возвращайте, пока не вернутся все созданные вами потоки»?

1 Ответ

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

Есть как минимум два других способа:

  1. Использовать pthread барьеры . Барьер имени используется в совершенно ином смысле, чем вы обычно слышите, когда говорите о параллельности. Здесь это примитив синхронизации, который позволяет каждому из набора потоков (официантов на нем) блокироваться до тех пор, пока все они не достигнут его, а затем разблокирует их все вместе. Сначала вы должны инициализировать барьер в каком-то общем месте с n+1 в качестве счетчика, а затем получить как саму функцию, так и все созданные им потоки n, чтобы завершить вызов. Предполагая, что вы делаете это таким образом, после возвращения из ожидания потоки n больше не могут получить доступ к общему состоянию;они должны немедленно вернуться.

  2. Создать то же самое (или его упрощенную версию) с помощью condvar и mutex. Защищенный мьютексом подсчет количества потоков n, которые все еще работают. Создавшая их функция может затем выполнить:

    pthread_mutex_lock(&cnt_mtx);
    while (count > 0) pthread_cond_wait(&cnt_cv, &cnt_mtx);
    pthread_mutex_unlock(&cnt_mtx);
    

В общем, я бы использовал здесь pthread_join. Вот для чего это.

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