pthread not giving expected output

时间:2019-04-17 02:27:05

标签: c++ operating-system pthreads semaphore

I am trying to implement the Producer-Consumer problem operating system using semaphore and pthread. But my output is totally different from expected. Here is my code:

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

    // define queue size
    #define QUEUE_SIZE 5

    // declare and initialize semaphore and read/write counter
    static int semaphore = 1;
    static int counter = 0;

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

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

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

    // function to wait for semaphore
    void wait()
    {
        while(semaphore<=0);
        semaphore--;
    }

    // function to signal the wait function
    void signal()
    {
        semaphore++;
    }

    void *Producer(void *ptr)
    {
        int i=0;
        std::ifstream input("string.txt");
        char temp;
        while(input>>temp)
        {
            wait();
            charQueue.push(temp);
            //std::cout<<"Producer:\nCounter: "<<counter<<" Semaphore: "<<semaphore<<std::endl;
            counter++;
            std::cout<<"Procuder Index: "<<i<<std::endl;
            i++;
            signal();
            sleep(2);
        }
        endOfFile = true;
        pthread_exit(NULL);
    }

    void *Consumer1(void *ptr)
    {
        std::cout<<"Entered consumer 1:"<<std::endl;
        int i = 0;
        while(counter<=0);
        while(!endOfFile)
        {
            while(counter<=0);
            wait();
            //std::cout<<"Consumer1:\nCounter: "<<counter<<" Semaphore: "<<semaphore<<std::endl;
            consumerArray1[i] = charQueue.front();
            charQueue.pop();
            i++;
            counter--;
            std::cout<<"Consumer1 index:"<<i<<" char: "<<consumerArray1[i]<<std::endl;
            signal();
            sleep(2);
        }
        consumerArray1[i] = '\0';
        pthread_exit(NULL);
    }

    void *Consumer2(void *ptr)
    {
        std::cout<<"Entered consumer 2:"<<std::endl;
        int i = 0;
        while(counter<=0);
        while(!endOfFile)
        {
            while(counter<=0);
            wait();
            //std::cout<<"Consumer2:\nCounter: "<<counter<<" Semaphore: "<<semaphore<<std::endl;
            consumerArray2[i] = charQueue.front();
            charQueue.pop();
            i++;
            counter--;
            std::cout<<"Consumer2 index: "<<i<<" char: "<<consumerArray2[i]<<std::endl;
            signal();
            sleep(4);
        }
        consumerArray2[i] = '\0';
        pthread_exit(NULL);
    }

    int main()
    {
        pthread_t thread[3];
        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;
        pthread_exit(NULL);
    }

The problem is my code, in some runs freezes(probably in an infinite loop) after the entire file has been read. And also both of the consumer functions read the same words even though I am popping it out after reading. Also the part of printing the array element that has been read just prints blank. Why are these problems happening? I am new to threads(as in coding using threads, I know theoretical concepts of threads) so please help me with this problem.

1 个答案:

答案 0 :(得分:2)

pthreads标准禁止在一个线程正在修改或可能正在修改另一个线程时访问该对象。您的var a = new Date("2018-04-17T07:00:00.000Z"); var b = new Date("2018-04-27T07:00:00.000Z"); var dayDif = (a - b) / 1000 / 60 / 60 / 24; wait函数在调用signal的线程可能正在访问它的同时,通过修改{{1}中的semaphore(在signal中)违反了此规则。您也可以使用wait进行此操作。

如果您在countersignal中所做的事情是合法的,则不需要waitsignal。您可以直接访问队列,就像直接访问wait一样。如果队列需要保护(正如我希望您知道的那样),那么semaphore也需要保护,原因也完全相同。

允许编译器优化此代码:

semaphore

此代码:

while(semaphore<=0);

为什么?因为它知道没有其他线程可以修改if (semaphore<=0) { while (1); } ,而该线程却可以访问它,因为该标准禁止这样做。因此,没有必要多次阅读。

您需要使用实际的符号和/或锁。