在使用pthread和信号量实现生产者-消费者问题时需要帮助 [英] Need help in implementing the Producer-Consumer problem with pthread and semaphore

查看:204
本文介绍了在使用pthread和信号量实现生产者-消费者问题时需要帮助的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用pthread和semaphore在C ++中实现生产者和消费者问题.我有一个生产者和两个消费者.我的生产者从文件中读取一个字符串,并将其逐个字符存储在队列中.消费者从字符串中读取内容,并也一个字符地存储在一个char字符中.问题是我的使用者中只有一个正在从队列中读取,另一个则不在,并且其数组保持为空.我该如何解决此问题.这是我的程序:

I am trying to implement the Producer and Consumer problem in C++ using pthread and semaphore. I have one Producer and two consumers. My producer reads a string from a file and stores it in a queue character by character. The consumers read from the string and store in a char character also one by one. The problem is that only one of my Consumer is reading from the queue, other is not and its array is remaining empty. How do I fix this problem. Here is my program:

#include<iostream>
#include<pthread.h>
#include<fstream>
#include<unistd.h>
#include<semaphore.h>
#include<queue>

// define queue size
#define QUEUE_SIZE 5

// declare and initialize semaphore and read/write counter
static sem_t mutex,mutex1;
//static int counter = 0;

// Queue for saving characters
static std::queue<char> charQueue;

// indicator for end of file
static bool endOfFile = false;

// save arrays
static char consumerArray1[100];
static char consumerArray2[100];


void *Producer(void *ptr)
{
    int i=0;
    std::ifstream input("string.txt");
    char temp;
    while(input>>temp)
    {
        sem_wait(&mutex);
        charQueue.push(temp);
        sem_post(&mutex1);
        sem_post(&mutex);
        //counter++;
        std::cout<<"Procuder Index: "<<i<<std::endl;
        i++;

        sleep(6);
    }
    endOfFile = true;
    pthread_exit(NULL);
}

void *Consumer1(void *ptr)
{
    std::cout<<"Entered consumer 1:"<<std::endl;
    int i = 0;
    sem_wait(&mutex1);
    //while(charQueue.empty());
    sem_post(&mutex1);
    while(!endOfFile)// || !charQueue.empty())
    {
        sem_wait(&mutex1);


        sem_wait(&mutex);

        std::cout<<"Consumer1 index:"<<i<<" char: "<<charQueue.front()<<std::endl;
        consumerArray1[i] = charQueue.front();
        charQueue.pop();
        //std::cout<<charQueue.size()<<std::endl;

        sem_post(&mutex1);
        i++;
        //counter--;

        sem_post(&mutex);
        sleep(2);
    }
    consumerArray1[i] = '\0';
    pthread_exit(NULL);
}

void *Consumer2(void *ptr)
{
    std::cout<<"Entered consumer 2:"<<std::endl;
    int i = 0;
    sem_wait(&mutex1);
    //while(charQueue.empty());
    sem_post(&mutex1);

    while(!endOfFile)//  || charQueue.empty())
    {
        sem_wait(&mutex1);


        sem_wait(&mutex);

        std::cout<<"Consumer2 index: "<<i<<" char: "<<charQueue.front()<<std::endl;
        consumerArray2[i] = charQueue.front();
        charQueue.pop();
        sem_post(&mutex1);
        i++;
        //counter--;

        sem_post(&mutex);
        sleep(4);
    }
    consumerArray2[i] = '\0';
    pthread_exit(NULL);
}

int main()
{
    pthread_t thread[3];
    sem_init(&mutex,0,1);
    sem_init(&mutex1,0,1);
    pthread_create(&thread[0],NULL,Producer,NULL);
    int rc = pthread_create(&thread[1],NULL,Consumer1,NULL);
    if(rc)
    {
        std::cout<<"Thread not created"<<std::endl;
    }
    pthread_create(&thread[2],NULL,Consumer2,NULL);
    pthread_join(thread[0],NULL);pthread_join(thread[1],NULL);pthread_join(thread[2],NULL);
    std::cout<<"First array: "<<consumerArray1<<std::endl;
    std::cout<<"Second array: "<<consumerArray2<<std::endl;
    sem_destroy(&mutex);
    sem_destroy(&mutex1);
    pthread_exit(NULL);
}

我还在charQueue.empty()charQueue.push()的访问周围添加了信号灯,但输出没有变化.我该怎么办?

I added semaphore around the access of charQueue.empty() and charQueue.push() as well, but no change in output. what else should I do?

推荐答案

您遇到的问题与以前相同.您的Consumer1函数可以调用charQueue.empty,而您的Producer函数可以调用charQueue.push(temp);.您可能无法在一个线程中访问一个对象,而另一个线程正在或可能正在修改它.您需要使用互斥体,信号量或其他某种形式的同步原语来保护charQueue.

You have the same problem that you had before. Your Consumer1 function can call charQueue.empty while your Producer function can be calling charQueue.push(temp);. You may not access an object in one thread while another thread is, or might be, modifying it. You either need to protect charQueue with a mutex, with a semaphore, or with some other form of synchronization primitive.

同样,编译器可以自由地优化如下代码:

Again, the compiler is free to optimize code like this:

while(charQueue.empty());

要这样编码:

if (charQueue.empty()) while (1);

为什么?因为您的代码可能随时都在访问charQueue.并且明确禁止一个线程修改对象,而另一个线程可能正在访问它.因此,允许编译器假定charQueue在执行此循环时不会被修改,因此无需多次检查其是否为空.

Why? Because your code may be accessing charQueue at any time. And it is expressly prohibited for one thread to modify an object while another thread may be accessing it. Therefore, the compiler is permitted to assume that charQueue will not be modified while this loop is executing and so there is no need to check it for emptiness more than once.

您有经验.使用它们来确保一次只有一个线程可以触摸charQueue.

You have sempahores. Use them to ensure that only one thread might touch charQueue at a time.

这篇关于在使用pthread和信号量实现生产者-消费者问题时需要帮助的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆