我的目标是使用多个工作线程处理多个核心上的数据,然后在主线程中进一步处理结果。我在linux上工作,我想使用pthreads。我创建了一个简单的例子来学习如何正确地做到这一点。我有一个主线程名为"回调"和4个工人线程。这个想法是主线程通知工作线程开始处理,然后4个线程在主线程完成时发出信号,主线程在所有4个线程通知它们完成后退出。我希望4个工作线程能够并行运行,所以我不希望任何这些线程等待其他线程。在我的例子中,我试图让每个线程休眠不同的持续时间(1,2,3和4秒),并认为代码将在4秒后退出(即当工作线程4有完成等待4秒)。
出于某种原因,我的代码不正确,并且它总是立即退出,打印出来:
thread 3 start (sleeping 3000 ms)
thread 2 start (sleeping 2000 ms)
thread 1 start (sleeping 1000 ms)
thread 4 start (sleeping 4000 ms)
thread 1 stop
thread 2 stop
thread 3 stop
thread 4 stop
Main(): Waited on 5 threads. Done.
所以线程确实似乎以正确的顺序退出,但程序运行不需要4秒。
这里发生了什么?我已粘贴下面的代码
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
// based on https://computing.llnl.gov/tutorials/pthreads/#ConditionVariables
#define DUR 1000
#define NUM_THREADS 5
int state = 0;
pthread_mutex_t mutex;
pthread_cond_t conddone;
pthread_cond_t condwork;
void* callback(void* t) {
// signal worker threads to start work
pthread_mutex_lock(&mutex);
pthread_cond_broadcast(&condwork);
pthread_mutex_unlock(&mutex);
// wait for worker threads to finish
pthread_mutex_lock(&mutex);
while (state < 4)
pthread_cond_wait(&conddone, &mutex);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void* worker(void* t) {
long id = (long)t;
// wait for signal from callback to start doing work
pthread_mutex_lock(&mutex);
pthread_cond_wait(&condwork, &mutex);
pthread_mutex_unlock(&mutex);
// do work
printf("thread %d start (sleeping %d ms)\n", id, id * DUR);
usleep(id * DUR);
printf(" thread %d stop\n", id);
// tell callback we're done
pthread_mutex_lock(&mutex);
state++;
pthread_cond_signal(&conddone);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
int i, rc;
pthread_t threads[5];
pthread_attr_t attr;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init (&condwork, NULL);
pthread_cond_init (&conddone, NULL);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&threads[0], &attr, callback, (void *)0);
pthread_create(&threads[1], &attr, worker, (void *)1);
pthread_create(&threads[2], &attr, worker, (void *)2);
pthread_create(&threads[3], &attr, worker, (void *)3);
pthread_create(&threads[4], &attr, worker, (void *)4);
for (i=0; i<NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
}
printf ("Main(): Waited on %d threads. Done.\n", NUM_THREADS);
pthread_attr_destroy(&attr);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&condwork);
pthread_cond_destroy(&conddone);
pthread_exit(NULL);
}
答案 0 :(得分:1)
您的直接问题只是usleep()
睡眠微秒而不是毫秒,因此您的线程正在睡眠的时间是您打算的千分之一。
但是,您确实遇到了另一个问题:您的condwork
条件变量未与共享状态的谓词配对(例如state < 4
变量的谓词conddone
。如果其中一个工作线程在“回调”线程执行pthread_cond_wait()
后执行pthread_cond_broadcast()
,则工作人员将无限期地等待。
您可以通过将state
变量初始化为-1
来解决此问题:
int state = -1;
让你的员工等待谓词state < 0
:
// wait for signal from callback to start doing work
pthread_mutex_lock(&mutex);
while (state < 0)
pthread_cond_wait(&condwork, &mutex);
pthread_mutex_unlock(&mutex);
并通过将状态设置为0来使“回调”向工作人员发出信号:
// signal worker threads to start work
pthread_mutex_lock(&mutex);
state = 0;
pthread_cond_broadcast(&condwork);
pthread_mutex_unlock(&mutex);