【问题标题】:pthread not giving expected outputpthread没有给出预期的输出
【发布时间】:2019-09-07 04:45:37
【问题描述】:

我正在尝试使用信号量和 pthread 实现生产者-消费者问题操作系统。但我的输出与预期完全不同。这是我的代码:

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

问题是我的代码在读取整个文件后在某些运行中冻结(可能处于无限循环中)。即使我在阅读后将其弹出,这两个消费者功能也会读取相同的单词。此外,打印已读取的数组元素的部分仅打印空白。为什么会出现这些问题?我是线程新手(就像使用线程编码一样,我知道线程的理论概念)所以请帮我解决这个问题。

【问题讨论】:

  • 您正在做的事情需要适当的联锁修改机制,或者一些互斥机制。有任何一个都可以工作。两者都不是竞争条件、挂起代码等的秘诀。您需要学习互斥锁、临界区等无关的东西,但与线程问题相比,this is wrong: while(!input.eof()) 是次要的。也没有任何输入验证。
  • @WhozCraig 我使用waitsignal 函数添加了互斥。这有什么问题?
  • 投反对票的原因是什么?这个问题有什么问题?
  • @ShantanuShinde 对于刚接触线程的人来说,开始尝试编写自己的同步原语是很奇怪的。这是一件非常复杂的事情,在您非常非常熟悉它们的使用方式之前不应该尝试。
  • @DavidSchwartz 好吧,我被分配了这样做的任务。

标签: c++ operating-system pthreads semaphore


【解决方案1】:

pthreads 标准禁止在一个线程中访问一个对象,而另一个线程正在或可能正在修改它。您的 waitsignal 函数通过修改 semaphore(在 signal 中)违反了此规则,而调用 wait 的线程可能正在访问它。您也可以使用 counter 来执行此操作。

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

允许编译器优化此代码:

while(semaphore<=0);

到此代码:

if (semaphore<=0) { while (1); }

为什么?因为它知道没有其他线程可以修改semaphore,而该线程可以访问它,因为标准禁止这样做。因此,没有理由多读一遍。

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

【讨论】:

  • 如何使用实际的信号量?
  • 将“pthread semaphore”打入您最喜欢的搜索引擎或阅读thisthis
  • 我更改了代码以使用信号量标头,但我现在面临不同的问题。我应该在哪里发布新代码?
  • 您可以提出一个新问题。确保在另一个线程正在或可能正在修改它时,不能在一个线程中访问任何对象(明确为此目的设计的同步对象除外)。
  • 什么是反对票?我已经根据stackoverflow的指南发布了这个问题。
猜你喜欢
  • 2018-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-22
  • 2019-07-16
  • 1970-01-01
相关资源
最近更新 更多