我正在使用pthreads解决生产者-消费者问题。基本上,生产者将文件读取到缓冲区,而使用者(至少一个,但不限于此)从缓冲区中获取条目,并逐个操作它们。
这是生产者:
//...Local stuff...
if(file){
while(fgets(line, 256, file)){
pthread_mutex_lock(&buffer_mutex);
while(data->buffer->buffer_items == data->buffer->buffer_size){
pthread_cond_wait(&buffer_full_cv, &buffer_mutex);}
data->buffer->buffer_items);
reads++;
add_to_head(data->buffer, line);
pthread_cond_broadcast(&buffer_ready_cv);
pthread_mutex_unlock(&buffer_mutex);
}
pthread_mutex_lock(&buffer_mutex);
work = 0;
pthread_mutex_unlock(&buffer_mutex);
fclose(file);
}
这是消费者:
//...Local stuff...
while(1){
pthread_mutex_lock(&buffer_mutex);
while(data->buffer->buffer_items == 0){
if(work)
pthread_cond_wait(&buffer_ready_cv, &buffer_mutex);
else if(!work && !data->buffer->buffer_items)
pthread_exit(NULL);
}
remove_from_tail(data->buffer, string_to_check);
data->buffer->buffer_items);
pthread_cond_signal(&buffer_full_cv);
pthread_mutex_unlock(&buffer_mutex);
for(unsigned int i = 0; i < data->num_substrings; i++){
cur_occurrence = strstr(string_to_check, data->substrings[i]);
while(cur_occurrence != NULL){
pthread_mutex_lock(&buffer_mutex);
data->occurrences[i]++;
cur_occurrence++;
cur_occurrence = strstr(cur_occurrence, data->substrings[i]);
pthread_mutex_unlock(&buffer_mutex);
}
}
}
似乎正在发生的事情是文件已被完全读取,并且仍有工作要做,但是由于生产者不再运行,因此消费者中的等待永远不会结束。
PS .:我也尝试了pthread_cond_signal而不是广播,但也没有用。
无论如何,我这里缺少什么吗?
最佳答案
似乎正在发生的事情是文件已被完全读取,并且仍有工作要做,但是由于生产者不再运行,因此消费者中的等待永远不会结束。
从技术上讲,这不是僵局。这是生产者/使用者线程配置的常见挑战。有多种方法可以解决此问题。
您可以使用一个特殊的缓冲区值(与空缓冲区分开),该值指示生产者已完成。 (如果您有多个使用者,则必须在缓冲区中保留此特殊值。)尽管这样的带内信令有时易于实现,但通常并不是一个好的设计。
如果您有多个生产者,则可能应将缓冲区与正在运行的生产者数量的计数器结合起来,从本质上在缓冲区中添加一个信号量。如果生产者数量达到零,则消费者需要退出。
加入所有使用者之后,产生生产者和使用者的线程可以使用pthread_cancel
,因此pthread_cond_wait
被中止。但是,要完全正确,这是棘手的,通常最好避免取消。
请注意,如果您有多个使用者,则每个人都需要在观察到达到数据结束状态后广播信号,以便其他使用者也有机会观察到它,
关于c - 使用pthread在生产者-消费者中出现死锁,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47107738/