C++ 生产者、消费者和我可爱的朋友

C++ 生产者、消费者和我可爱的朋友,c++,multithreading,c++11,pthreads,C++,Multithreading,C++11,Pthreads,我正在处理生产者-消费者(多线程)问题,遇到了死锁。我的问题是怎么做 我让多个生产商创建了n个产品,并将它们放入一个全局队列。如果队列中没有空间,生产者必须等待 我的消费者使用先到先得服务访问队列。如果队列中没有任何内容,消费者必须等待。消费者将消费产品的一部分,只有当产品完全消费后,才会将其从队列中移除。当没有更多的产品可供消费时,消费者将停止消费 当消费完第一个项目时,我会出现死锁。我使用一个互斥锁来锁定队列,使用两个条件变量来在队列中添加或删除项目时发出信号,使用一个信号量来跟踪正在使用的

我正在处理生产者-消费者(多线程)问题,遇到了死锁。我的问题是怎么做

我让多个生产商创建了n个产品,并将它们放入一个全局队列。如果队列中没有空间,生产者必须等待

我的消费者使用先到先得服务访问队列。如果队列中没有任何内容,消费者必须等待。消费者将消费产品的一部分,只有当产品完全消费后,才会将其从队列中移除。当没有更多的产品可供消费时,消费者将停止消费

当消费完第一个项目时,我会出现死锁。我使用一个互斥锁来锁定队列,使用两个条件变量来在队列中添加或删除项目时发出信号,使用一个信号量来跟踪正在使用的项目总数

你知道为什么会死锁吗

输入:2(生产者)3(消费者)5(要生产的项目)2(队列大小)0(不适用)50(数量)1(种子)

制作人:

#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;
}