下面显示了一种方法,使用条件变量和其他一些变量;虽然可能有更好的方法。评论应该显示它是如何工作的。当然,您必须修改内容以适应您的实际情况;例如可能涉及循环等。
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;
}
不过,我要补充一点,我看不出什么时候有充分的理由这样做,而不仅仅是以更直接的方式保护资源。
编辑:在代码中添加了一些东西,显示了第二个条件变量,用于让主线程等待所有工作人员准备好。更改的部分在注释中标有“EDIT:”,如果不需要,可以省略。我还通过将增量activeThreads
移出线程函数来纠正竞争条件,并显示互斥锁的初始化等(没有错误处理)。