Как завершить все потоки сразу после завершения одного из потоков в си, используя толлько pthread_detach и pthread_join?

В Си можно завершить все потоки сразу после завершения одного из них, используя pthread_detach и pthread_join в сочетании с переменной-условием и мьютексом.

Первым шагом является создание и инициализация переменной-условия и мьютекса, которые будут использоваться для синхронизации потоков:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // инициализация мьютекса
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; // инициализация переменной-условия

Затем, для каждого потока, необходимо создать и запустить поток, передав ему свои аргументы и функцию, которая будет выполняться в потоке. При создании потока, необходимо установить его атрибут в состояние "detached" с помощью pthread_attr_setdetachstate:

pthread_t thread_id;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&thread_id, &attr, thread_function, (void*)arg);
pthread_attr_destroy(&attr);

Важно установить атрибут в состояние "detached", чтобы потоки автоматически освобождались после завершения, иначе при каждом завершении потока необходимо было бы явно освобождать его ресурсы с помощью pthread_join.

Далее, в функции каждого потока, необходимо выполнить необходимую логику и, если один поток завершил свою работу, вызвать pthread_cond_broadcast, чтобы оповестить остальные потоки:

void* thread_function(void* arg) {
    // Логика потока

    pthread_mutex_lock(&mutex);
    // ...проверка на завершение потока

    // Если поток завершился, оповестить остальные потоки
    pthread_cond_broadcast(&cond);
    pthread_mutex_unlock(&mutex);

    pthread_exit(NULL);
}

Наконец, в основном потоке, после создания и запуска всех потоков, необходимо вызвать поток, который будет ожидать на выполнение pthread_cond_wait с помощью цикла while и pthread_cond_timedwait:

pthread_mutex_lock(&mutex);

// Ждем завершения всех потоков
while (check_all_threads_finish() == 0) {
   struct timespec timeout;
   clock_gettime(CLOCK_REALTIME, &timeout);
   timeout.tv_sec += 1; // Таймаут на ожидание 1 секунду
   
   pthread_cond_timedwait(&cond, &mutex, &timeout);
}

pthread_mutex_unlock(&mutex);

Функция check_all_threads_finish будет проверять завершились ли все потоки:

int check_all_threads_finish() {
   // Логика проверки завершения всех потоков
   // Возвращает 1, если все потоки закончили работу, иначе возвращает 0
}

В результате, когда один из потоков завершится, вызывается pthread_cond_broadcast, который оповестит все остальные потоки, остановив их выполнение. Основной поток будет ждать, пока все потоки не завершат свою работу с помощью pthread_cond_wait или pthread_cond_timedwait и проверки функции check_all_threads_finish.

Таким образом, используя pthread_detach, pthread_join, pthread_cond_broadcast и pthread_cond_wait, можно завершить все потоки сразу после завершения одного из них в C.