问题描述
我正在尝试实现一种线程池,借此将线程保留在FIFO中并处理一堆图像.不幸的是,由于某种原因,即使我的cond_wait被信号通知,它也并不总是唤醒.
I'm trying to implement a sort of thread pool whereby I keep threads in a FIFO and process a bunch of images. Unfortunately, for some reason my cond_wait doesn't always wake even though it's been signaled.
// 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);
}
我错过了什么吗?它大约有一半的时间有效,所以我假设我在某个地方有比赛,但是我唯一能想到的就是我正在加紧互斥体吗?我读到一些有关在锁定之前不发信号的信息,但我不太了解发生了什么.
Am I missing something? It works about half of the time, so I would assume that I have a race somewhere, but the only thing I can think of is that I'm screwing up the mutexes? I read something about not signalling before locking or something, but I don't really understand what's going on.
有什么建议吗?
谢谢!
推荐答案
首先,您的示例显示将queueMutex
锁定在对pop_front
的调用周围,但没有对push_back
进行舍入.通常,除非您可以保证在所有爆破声发生之前进行所有推送,否则您都需要锁定两者.
Firstly, your example shows you locking the queueMutex
around the call to pop_front
, but not round push_back
. Typically you would need to lock round both, unless you can guarantee that all the pushes happen-before all the pops.
第二,您对pthread_cond_wait
的调用似乎没有关联的谓词.条件变量的典型用法是:
Secondly, your call to pthread_cond_wait
doesn't seem to have an associated predicate. Typical usage of condition variables is:
pthread_mutex_lock(&mtx);
while(!ready)
{
pthread_cond_wait(&cond,&mtx);
}
do_stuff();
pthread_mutex_unlock(&mtx);
在此示例中,ready
是由另一个线程设置的某个变量,而该线程持有对mtx
的锁定.
In this example, ready
is some variable that is set by another thread whilst that thread holds a lock on mtx
.
如果在调用pthread_cond_signal
时未在pthread_cond_wait
中阻塞等待线程,则该信号将被忽略.关联的ready
变量使您能够处理这种情况,还使您能够处理所谓的虚假唤醒,其中返回pthread_cond_wait
的调用而无需从另一个线程.
If the waiting thread is not blocked in the pthread_cond_wait
when pthread_cond_signal
is called then the signal will be ignored. The associated ready
variable allows you to handle this scenario, and also allows you to handle so-called spurious wake-ups where the call to pthread_cond_wait
returns without a corresponding call to pthread_cond_signal
from another thread.
这篇关于pthread_cond_wait永不阻塞-线程池的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!