В Си можно завершить все потоки сразу после завершения одного из них, используя 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.