【问题标题】:Producer consumer pthreads program not finishing生产者消费者 pthreads 程序未完成
【发布时间】:2017-10-19 21:48:03
【问题描述】:

所以我必须制作一个程序,它使用 4 个生产者线程和 4 个消费者线程,并使用一个一次保存 10 个随机数的数组。一旦该数组已满,生产者必须等到消费者消费完这 10 个数字,然后消费者再等待数组再次满。我必须用 1000 个随机数来做这个。

问题是程序从未真正完成,我不知道为什么。我正在用 20 个数字对其进行测试,但输出非常混乱且无序,这并没有让这变得更容易。我将代码和输出放在下面。

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <time.h>

// use 4 cons 4 prod
// instead of random number, use 1000 for all prod
// real time lib is optional
// Due thurs 11pm

using namespace std;

#define BSIZE 10
#define NUM_ITEMS 20
#define NUM_THREADS 8
#define NUM_PRODUCERS 4
#define NUM_CONSUMERS 4


int buf[BSIZE];
int nextin=0, nextout=0;

pthread_mutex_t lock;       // a shared lock veriale
pthread_cond_t empty, full;
bool isFull = false, isEmpty = false;
int bufCounter = 0;

void * producer(void *);    // function for producer thread
void * consumer(void *);    // function for consumer thread

pthread_t tid[NUM_THREADS];      // array of thread IDs


int main( int argc, char *argv[] ) 
{
    int i;

    pthread_cond_init(&full, NULL);
    pthread_cond_init(&empty, NULL);

    printf("\n **** Main Program creating threads **** \n");

    for (i = 0; i < NUM_PRODUCERS; i++)
        pthread_create(&tid[i], NULL, producer, NULL); // Creating producers 
    for (i = NUM_PRODUCERS; i < NUM_THREADS; i++)
        pthread_create(&tid[i], NULL, consumer, NULL); // Creating consumers

    for ( i = 0; i < NUM_THREADS; i++)
        pthread_join(tid[i], NULL);

    printf("\n *** main() reporting: all %d threads have terminated ***\n\n ", i);

    return 0; 

}  /* main */



void * producer(void * parm)
{
    int i, num;

    printf("\n ++++ Producer started ++++ \n");

    for(i=0; i < NUM_ITEMS; i++)
    { // produce items  

        num = rand() % 1000;

        pthread_mutex_lock(&lock);      // lock the buffer when adding num

        if (isFull == true)
            pthread_cond_wait(&empty, &lock);

        buf[nextin++] = num;

        nextin %= BSIZE;    // make the buffer circular
        bufCounter++; // Increment bufCounter

        if (bufCounter == BSIZE){
            isFull = true;
            isEmpty = false;
        }
        pthread_cond_signal(&full);
        pthread_mutex_unlock(&lock);    // get out the critical section 

    }


    printf("\n ++++ Producer exiting ++++\n");
    pthread_exit(0);
}    

void * consumer(void * parm)
{
    int i, num;

    printf("\n ==== Consumer started ==== \n");

    for(i=0; i < NUM_ITEMS; i++)
    {       
        // get item from the buffer and consume it

        pthread_mutex_lock(&lock);      // lock the buffer when removing item

        if (isEmpty == true)
            pthread_cond_wait(&full, &lock);

        num = buf[nextout++];
        nextout %= BSIZE;       // make the buffer circular
        bufCounter--;       

        printf(" Consuming item #[%d]: %d\n", i, num);

        if (bufCounter == 0){
            isEmpty = true;
            isFull = false;
        }   
        pthread_cond_signal(&empty);
        pthread_mutex_unlock(&lock);      // unlock the buffer and get out CS

    }


    printf("\n ==== Consumer exiting ====\n");
    pthread_exit(0);
}

非常感谢任何帮助,而且我知道这里有很多代码。对不起。

编辑:这是完整的输出。

 **** Main Program creating threads ****

 ++++ Producer started ++++

 ++++ Producer started ++++

 ++++ Producer started ++++

 ++++ Producer started ++++

 ==== Consumer started ====
 Consuming item #[0]: 838
 Consuming item #[1]: 758
 Consuming item #[2]: 113
 Consuming item #[3]: 515

 ==== Consumer started ====
 Consuming item #[4]: 51
 Consuming item #[5]: 627

 ==== Consumer started ====

 ==== Consumer started ====
 Consuming item #[6]: 10
 Consuming item #[7]: 419
 Consuming item #[8]: 212
 Consuming item #[9]: 86
 Consuming item #[10]: 749
 Consuming item #[0]: 225
 Consuming item #[11]: 543
 Consuming item #[1]: 89
 Consuming item #[2]: 84
 Consuming item #[3]: 137
 Consuming item #[0]: 566
 Consuming item #[0]: 183
 Consuming item #[1]: 978
 Consuming item #[2]: 767
 Consuming item #[3]: 495
 Consuming item #[4]: 311
 Consuming item #[5]: 367
 Consuming item #[6]: 54
 Consuming item #[7]: 966
 Consuming item #[12]: 882
 Consuming item #[1]: 736
 Consuming item #[2]: 524
 Consuming item #[3]: 505
 Consuming item #[4]: 60
 Consuming item #[5]: 394
 Consuming item #[6]: 102
 Consuming item #[7]: 851
 Consuming item #[8]: 67
 Consuming item #[9]: 653
 Consuming item #[10]: 561
 Consuming item #[11]: 96

 ++++ Producer exiting ++++
 Consuming item #[8]: 31
 Consuming item #[9]: 754
 Consuming item #[10]: 188
 Consuming item #[11]: 85
 Consuming item #[12]: 143
 Consuming item #[13]: 967
 Consuming item #[14]: 145
 Consuming item #[15]: 406
 Consuming item #[16]: 165
 Consuming item #[17]: 403
 Consuming item #[4]: 562
 Consuming item #[5]: 628
 Consuming item #[13]: 920
 Consuming item #[14]: 834
 Consuming item #[15]: 803
 Consuming item #[16]: 444
 Consuming item #[6]: 962
 Consuming item #[7]: 318

 ++++ Producer exiting ++++
 Consuming item #[8]: 422
 Consuming item #[9]: 327
 Consuming item #[10]: 457
 Consuming item #[11]: 945
 Consuming item #[12]: 479
 Consuming item #[13]: 983
 Consuming item #[14]: 751
 Consuming item #[18]: 894

 ++++ Producer exiting ++++
 Consuming item #[19]: 670

 ==== Consumer exiting ====
 Consuming item #[15]: 259
 Consuming item #[16]: 248
 Consuming item #[17]: 353
 Consuming item #[18]: 757
 Consuming item #[17]: 629
 Consuming item #[18]: 306
 Consuming item #[19]: 606

 ==== Consumer exiting ====
 Consuming item #[12]: 990
 Consuming item #[13]: 738
 Consuming item #[14]: 516
 Consuming item #[15]: 414
 Consuming item #[16]: 262

 ++++ Producer exiting ++++
 Consuming item #[17]: 116

您可以看到程序只是停止并停在那里,所以我不确定它是否刚刚完成所有数字,但它会再次被调用等待。

【问题讨论】:

  • 将输出复制粘贴到问题本身。我拒绝访问我第一次看到的外部网站。
  • @Algirdas Preidžius 我将其添加到帖子中。这只是一个 Gyazo 链接,它是一个程序,可让您截取屏幕截图,然后将其上传到他们的网站。
  • 从未见过 - 不要相信它。复制粘贴总是比截屏、上传和复制粘贴链接更容易。更不用说,所有信息都需要出现在问题本身中,而不是在外部网站中。
  • 文字最好。比图像更容易解析和搜索。
  • void * consumer(void * parm)void * producer(void * parm) 不要返回。程序无效,之后所有赌注都被取消,所以你不妨扔一个return NULL;

标签: c++ multithreading unix pthreads


【解决方案1】:
    if (bufCounter == BSIZE){
        isFull = true;
        isEmpty = false;
    }

这是错误的。您刚刚将一个项目添加到缓冲区。缓冲区无条件非空。

    if (bufCounter == 0){
        isEmpty = true;
        isFull = false;
    }   

同样,您刚刚从缓冲区中删除了一个项目。它无条件地不满。

在这两种情况下,其中一个分配应该在if 之外。 OTOH,如果状态没有改变,则无需向 condvar 发出信号,因此应将 pthread_cond_signal 移动到 if 内。

最后,如果您使用 C++ 编写,请使用 C++ 工具。 C++ 现在支持多线程,因此无需求助于特定于操作系统的 API。

Here 是固定程序,稍作改动以使其成为 C 程序。

【讨论】:

  • 非常感谢您,您是救生员。现在这一切都变得更有意义了。
猜你喜欢
  • 2011-05-04
  • 2011-08-29
  • 1970-01-01
  • 2017-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-03
  • 1970-01-01
相关资源
最近更新 更多