我正在尝试实现一种线程池,我将线程保存在FIFO中并处理一堆图像。不幸的是,由于某些原因,即使已经发出信号,我的cond_wait并不总是被唤醒。
// Initialize the thread pool
for(i=0;i<numThreads;i++)
{
pthread_t *tmpthread = (pthread_t *) malloc(sizeof(pthread_t));
struct Node* newNode;
newNode=(struct Node *) malloc(sizeof(struct Node));
newNode->Thread = tmpthread;
newNode->Id = i;
newNode->threadParams = 0;
pthread_cond_init(&(newNode->cond),NULL);
pthread_mutex_init(&(newNode->mutx),NULL);
pthread_create( tmpthread, NULL, someprocess, (void*) newNode);
push_back(newNode, &threadPool);
}
for() //stuff here
{
//...stuff
pthread_mutex_lock(&queueMutex);
struct Node *tmpNode = pop_front(&threadPool);
pthread_mutex_unlock(&queueMutex);
if(tmpNode != 0)
{
pthread_mutex_lock(&(tmpNode->mutx));
pthread_cond_signal(&(tmpNode->cond)); // Not starting mutex sometimes?
pthread_mutex_unlock(&(tmpNode->mutx));
}
//...stuff
}
destroy_threads=1;
//loop through and signal all the threads again so they can exit.
//pthread_join here
}
void *someprocess(void* threadarg)
{
do
{
//...stuff
pthread_mutex_lock(&(threadNode->mutx));
pthread_cond_wait(&(threadNode->cond), &(threadNode->mutx));
// Doesn't always seem to resume here after signalled.
pthread_mutex_unlock(&(threadNode->mutx));
} while(!destroy_threads);
pthread_exit(NULL);
}
我错过了什么吗?它的工作时间大约是一半,所以我认为我在某个地方有种族,但我能想到的唯一一件事就是我搞砸了互斥体?我读过一些关于在锁定之前不发信号的事情,但我真的不明白发生了什么。
有什么建议吗?
谢谢!
答案 0 :(得分:3)
首先,您的示例显示您将queueMutex
锁定在pop_front
的调用周围,而不是push_back
。通常你需要锁定两者,除非你能保证在所有的弹出之前发生所有的推动。
其次,您对pthread_cond_wait
的调用似乎没有关联的谓词。条件变量的典型用法是:
pthread_mutex_lock(&mtx);
while(!ready)
{
pthread_cond_wait(&cond,&mtx);
}
do_stuff();
pthread_mutex_unlock(&mtx);
在此示例中,ready
是由另一个线程设置的变量,而该线程在mtx
上持有锁。
如果在调用pthread_cond_wait
时pthread_cond_signal
中未阻止等待线程,则将忽略该信号。关联的ready
变量允许您处理这种情况,并且还允许您处理所谓的虚假唤醒,其中pthread_cond_wait
的调用返回而没有相应的调用来自另一个帖子的pthread_cond_signal
。
答案 1 :(得分:-1)
我不确定,但我认为您在调用pthread_cond_signal(&amp;(tmpNode-&gt; cond))之前不必(必须)锁定线程池中的互斥锁;否则,被唤醒的线程将无法锁定互斥锁作为pthread_cond_wait(&amp;(threadNode-&gt; cond),&amp;(threadNode-&gt; mutx))的一部分;操作