C++ 生产者、消费者和我可爱的朋友
我正在处理生产者-消费者(多线程)问题,遇到了死锁。我的问题是怎么做 我让多个生产商创建了n个产品,并将它们放入一个全局队列。如果队列中没有空间,生产者必须等待 我的消费者使用先到先得服务访问队列。如果队列中没有任何内容,消费者必须等待。消费者将消费产品的一部分,只有当产品完全消费后,才会将其从队列中移除。当没有更多的产品可供消费时,消费者将停止消费 当消费完第一个项目时,我会出现死锁。我使用一个互斥锁来锁定队列,使用两个条件变量来在队列中添加或删除项目时发出信号,使用一个信号量来跟踪正在使用的项目总数 你知道为什么会死锁吗 输入:2(生产者)3(消费者)5(要生产的项目)2(队列大小)0(不适用)50(数量)1(种子) 制作人:C++ 生产者、消费者和我可爱的朋友,c++,multithreading,c++11,pthreads,C++,Multithreading,C++11,Pthreads,我正在处理生产者-消费者(多线程)问题,遇到了死锁。我的问题是怎么做 我让多个生产商创建了n个产品,并将它们放入一个全局队列。如果队列中没有空间,生产者必须等待 我的消费者使用先到先得服务访问队列。如果队列中没有任何内容,消费者必须等待。消费者将消费产品的一部分,只有当产品完全消费后,才会将其从队列中移除。当没有更多的产品可供消费时,消费者将停止消费 当消费完第一个项目时,我会出现死锁。我使用一个互斥锁来锁定队列,使用两个条件变量来在队列中添加或删除项目时发出信号,使用一个信号量来跟踪正在使用的
#include <pthread.h>
#include <semaphore.h>
#include "producerConsumer.h"
#include <iostream>
#include <sys/time.h>
void* producer(void* args)
{
tProducer producer = *((tProducer*) args);
tProduct products[producer.products];
unsigned int queueMax = producer.queueMax;
timeval time;
std::string output;
for(int i = 0; i < producer.products; i++)
{
//Create item
products[i].productId = i;
products[i].life = producer.lifeOfProduct;
gettimeofday(&time, NULL);
products[i].timestamp = time.tv_sec;
//Lock and add to queue
pthread_mutex_lock(&queueLock);
//Queue is full and must wait
if(queue.size() >= queueMax)
{
output = "Producer: " + std::to_string(producer.id) + " is waiting\n";
std::cout << output;
pthread_cond_wait(&removeSignal, &queueLock);
}
//Debug message
output = "Producer: " + std::to_string(producer.id) + " is producing.\n";
std::cout << output;
//Add item to queue and signal
queue.push(products[i]);
pthread_cond_signal(&addSignal);
pthread_mutex_unlock(&queueLock);
//pthread_cond_signal(&addSignal);
//Debug message
output = "Producer: " + std::to_string(producer.id) + " just produced.\n";
std::cout << output;
}
pthread_exit(NULL);
}
#包括
#包括
#包括“producerConsumer.h”
#包括
#包括
无效*生产者(无效*参数)
{
tProducer producer=*((tProducer*)参数);
t产品[生产者.产品];
unsigned int queueMax=producer.queueMax;
timeval时间;
std::字符串输出;
对于(int i=0;i=queueMax)
{
output=“Producer:”+std::to_字符串(Producer.id)+“正在等待\n”;
std::cout我最终找到了答案。我的消费者中的sem_trywait在消费未完成的项目时会减少。消费者中的sem_wait会阻塞,因为没有剩余项目。这可能不是你的问题,但我应该指出,由于虚假的唤醒,pthread\u cond\u wait()
允许在没有实际处理的情况下返回。这就是为什么对pthread\u cond\u wait()
的调用应该包装在一个循环中,以检查等待的不变量是否实际发生。我发现问题出在sem\u trywait()上。当项目没有实际消费时,它正在递减。不过这是一个很好的建议。您可以调用sem\u trywait(&totalProductsLeft)
查看是否还有剩余的产品。此调用将立即成功递减计数器,或者如果计数为0,将返回错误代码。但是,然后您可以调用sem\u wait(&totalProductsLeft)pthread\u cond\u signal(&removeSignal)之后
当产品生命周期结束时;这意味着在产品生命周期结束的情况下,您正在加倍减少信号量(并且在其计数达到0时可能会死锁)。Wups,看起来您自己得到了它!恭喜。
#include <pthread.h>
#include <semaphore.h>
#include "producerConsumer.h"
#include <iostream>
void* consumer(void* args)
{
tConsumer consumer = *((tConsumer*) args);
int id = consumer.id;
int quantum = consumer.quantum;
std::string output;
while(true)
{
//Exit when nothing else is being created
if(sem_trywait(&totalProductsLeft) < 0)
{
break;
}
//Subtract life from product, and remove from queue if done
pthread_mutex_lock(&queueLock);
//Wait until item is in queue
if(queue.size() <= 0)
{
//Debug message
output = "Consumer: " + std::to_string(id) + " is waiting.\n";
std::cout << output;
pthread_cond_wait(&addSignal, &queueLock);
}
//Debug message
output = "Consumer: " + std::to_string(id) + " is ready.\n";
std::cout << output;
tProduct& product = queue.front();
product.life -= quantum;
//Item is done being consumed
if(product.life <= 0)
{
//Debug message
output = "Product: " + std::to_string(product.productId) + " is dead.\n";
std::cout << output;
//Remove a spot
queue.pop();
pthread_cond_signal(&removeSignal);
sem_wait(&totalProductsLeft);
}
else
{
//Debug message
output = "Product: " + std::to_string(product.life) + "hp is not done.\n";
std::cout << output;
}
pthread_mutex_unlock(&queueLock);
}
//May need to broadcast
pthread_exit(NULL);
}
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <pthread.h>
#include <semaphore.h>
#include "producerConsumer.h"
std::queue<tProduct> queue;
pthread_cond_t addSignal;
pthread_cond_t removeSignal;
sem_t totalProductsLeft;
pthread_mutex_t queueLock;
int main(int argc, char** argv)
{
//Handle input
const int NUM_INPUTS = 8;
int numberProducers;
int numberConsumers;
int numberOfProducts;
int queueSize;
int scheduleType;
int quantum;
int seed;
//Error check for input
if(argc != NUM_INPUTS)
{
std::cout << "Invalid number of arguments.\n";
return -1;
}
//Grab arguments
numberProducers = atoi(argv[1]);
numberConsumers = atoi(argv[2]);
numberOfProducts = atoi(argv[3]);
queueSize = atoi(argv[4]);
scheduleType = atoi(argv[5]);
quantum = atoi(argv[6]);
seed = atoi(argv[7]);
//Get rid of warnings for now
std::cout << numberOfProducts << std::endl;
std::cout << queueSize << std::endl;
std::cout << quantum << std::endl;
std::cout << seed << std::endl;
std::cout << scheduleType << std::endl;
//Create threads
pthread_t producerThreads[numberProducers];
pthread_t consumerThreads[numberConsumers];
tProducer producerArgs[numberProducers];
tConsumer consumerArgs[numberConsumers];
//Initialize global
pthread_mutex_init(&queueLock, NULL);
pthread_cond_init(&addSignal, NULL);
pthread_cond_init(&removeSignal, NULL);
std::cout << "Total Items: " << (numberProducers * numberOfProducts) << std::endl;
sem_init(&totalProductsLeft, 0, numberProducers * numberOfProducts);
//Start threads
srand(seed);
for(int i = 0; i < numberProducers; i++)
{
producerArgs[i].id = i;
producerArgs[i].products = numberOfProducts;
producerArgs[i].lifeOfProduct = rand() % 1024;
producerArgs[i].queueMax = queueSize;
pthread_create(&(producerThreads[i]), 0, producer, &producerArgs[i]);
}
for(int i = 0; i < numberConsumers; i++)
{
consumerArgs[i].id = i;
consumerArgs[i].quantum = quantum;
pthread_create(&(consumerThreads[i]), 0, consumer, &consumerArgs[i]);
}
//Wait for threads to end
for(int i = 0; i < numberProducers; i++)
{
pthread_join(producerThreads[i], NULL);
}
for(int i = 0; i < numberConsumers; i++)
{
pthread_join(consumerThreads[i], NULL);
}
return 0;
}