Ниже показан один из способов сделать это, используя условную переменную и несколько других переменных; хотя могут быть и лучшие способы. Комментарии должны показать, как это работает. Конечно, вам придется изменить вещи, чтобы они соответствовали вашей реальной ситуации; например, могут быть задействованы циклы и т. д.
int activeThreads = 0; /* number of threads currently going */
int waitingThreads = 0; /* number of threads waiting on the condition */
int readyFlag = 0; /* flag to tell the threads to proceed when signaled */
pthread_cond_t cond; /* condition to wait on / signal */
pthread_mutex_t mtx; /* mutex for the above */
pthread_cond_t condWaiting; /* EDIT: additional condition variable to signal
* when each thread starts waiting */
void *threadFunc(void *arg)
{
/* Edit: Rather than incrementing 'activeThreads' here, it should be done
* in the main thread when each thread is created (to avoid a race) */
/* ...do stuff... */
/* When the threads should wait, do this (they wait for 'readyFlag' to be
* set, but also adjust the waiting thread count so the main thread can
* determine whether to broadcast) */
pthread_mutex_lock(&mtx);
if (readyFlag == 0) {
waitingThreads++;
do {
pthread_cond_signal(&condWaiting); /* EDIT: signal the main thread when
* a thread begins waiting */
pthread_cond_wait(&cond,&mtx);
} while (readyFlag == 0);
waitingThreads--;
}
pthread_mutex_unlock(&mtx);
/* ...more stuff... */
/* When threads terminate, they decrement the active thread count */
pthread_mutex_lock(&mtx);
activeThreads--;
pthread_cond_signal(&condWaiting); /* EDIT: also signal the main thread
* when a thread exits to make it
* recheck the waiting thread count if
* waiting for all threads to wait */
pthread_mutex_unlock(&mtx);
return NULL;
}
int main(int argc, char *argv[])
{
/* Edit: Showing some code to initialize the mutex, condition variable(s),
* etc., and create some threads -- modify as needed */
pthread_mutex_init(&mtx,NULL);
pthread_cond_init(&cond,NULL);
pthread_cond_init(&condWaiting,NULL); /* EDIT: if main thread should block
* until all threads are waiting */
activeThreads = waitingThreads = readyFlag = 0;
/* Edit: Increment 'activeThreads' here rather than in the thread function,
* to avoid a race (if the main thread started waiting for the others
* when not all had incremented the count yet, the main thread might end
* up waiting for fewer threads to be ready -- though it's unlikely */
#define NUM_THREADS 10
pthread_t workers[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
/* should use appropriate thread attributes */
if (pthread_create(&workers[i],NULL,threadFunc,NULL) == 0)
activeThreads++;
}
/* ...do stuff... */
/* Set 'readyFlag' and do condition broadcast IF all threads are waiting,
* or just carry on if they aren't */
pthread_mutex_lock(&mtx);
if ((activeThreads != 0) && (activeThreads == waitingThreads)) {
readyFlag = 1;
pthread_cond_broadcast(&cond);
}
pthread_mutex_unlock(&mtx);
/* EDIT: OR.. to wait until all threads are waiting and then broadcast, do
* this instead: */
pthread_mutex_lock(&mtx);
while (waitingThreads < activeThreads) { /* wait on 'condWaiting' until all
* active threads are waiting */
pthread_cond_wait(&condWaiting,&mtx);
}
if (waitingThreads != 0) {
readyFlag = 1;
pthread_cond_broadcast(&cond);
}
pthread_mutex_unlock(&mtx);
/* ...more stuff... */
/* If needed, you can clear the flag when NO threads are waiting.. */
pthread_mutex_lock(&mtx);
if (waitingThreads == 0)
readyFlag = 0;
pthread_mutex_unlock(&mtx);
/* ...even more stuff... */
return 0;
}
Я бы добавил, однако, что я не понимаю, когда была бы веская причина сделать это, а не просто защитить ресурсы более простым способом.
РЕДАКТИРОВАТЬ: Добавил некоторые вещи в код, показывая вторую переменную условия, используемую, чтобы позволить основному потоку ждать, пока все рабочие будут готовы. Измененные детали помечаются «РЕДАКТИРОВАТЬ:» в комментариях и могут быть пропущены, если не нужны. Я также исправил условие гонки, переместив приращение activeThreads
из функции потока, и показал инициализацию мьютекса и т. Д. (Без обработки ошибок).