【问题标题】:Irregular print statements in multiple producer consumer program多生产者消费者程序中的不规则打印语句
【发布时间】:2015-12-20 09:04:38
【问题描述】:

共享队列是一个。生产者和消费者都是两个。

下面是输出,之后我已经粘贴了程序:

我的问题是打印语句qDebug () << "\nConsumer: " << tId;,在顶部仍然没有先打印。我想知道为什么。


Producer  140588830992128  couldn't push any data since queue was already full. Length of queue is:  10
Removed by thread Consumer:  140588814206720 , Length of queue is:  9
Removed by thread Consumer:  140588814206720 , Length of queue is:  8
Removed by thread Consumer:  140588814206720 , Length of queue is:  7
Removed by thread Consumer:  140588814206720 , Length of queue is:  6
Removed by thread Consumer:  140588814206720 , Length of queue is:  5
Consumer:  140588814206720
Removed by thread Consumer:  140588814206720 , Length of queue is:  4
Removed by thread Consumer:  140588814206720 , Length of queue is:  3
Removed by thread Consumer:  140588814206720 , Length of queue is:  2
Consumer:  140588814206720
Removed by thread Consumer:  140588814206720 , Length of queue is:  1
Consumer:  140588814206720
Removed by thread Consumer:  140588814206720 , Length of queue is:  0

这是我编写的程序:

#include "mainwindow.h"
#include <QApplication>

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <iostream>
#include <QDebug>

pthread_mutex_t mutexVariable     = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  conditionVariable = PTHREAD_COND_INITIALIZER;

int numberOfActiveProducers;
int numberOfActiveConsumers;

QList <int> sharedQueue;
/*
 * `sharedQueue`'s size is assumed to be 10 ATM.
 * `sharedQueue` is supposed to be shared among two threads.
 * Producer threads will put the 1's in it, and Consumer threads will remove the 1's.
 * Assumption: `sharedQueue` can contain only 10 elements at a time.
 */

int sizeOfSharedQueue;

//  This function is run by the `Producer` threads.
void *producerThreadFunction (void *arg) {
    Q_UNUSED (arg);

    while (1) {
        pthread_t tId = pthread_self();
        qDebug () << "\nProducer: " << tId;

        pthread_mutex_lock (&mutexVariable);

        if (sharedQueue.length () < 10) {
            sharedQueue.push_back (1);
            qDebug () << "\nPushed by Producer " << tId << ": " << "Length of queue is: " << sharedQueue.length ();
        }
        else {
            qDebug () << "\nProducer " << tId << " has no work to do since quque is full, and is now in waiting mode. Length of queue is: " << sharedQueue.length ();
            pthread_cond_wait (&conditionVariable, &mutexVariable);
        }

        pthread_mutex_unlock (&mutexVariable);
    }

    return NULL;
}

//  This function is run by the `Consumer` threads.
void *consumerThreadFunction (void *arg) {
    Q_UNUSED (arg);

    while (1) {
        pthread_t tId = pthread_self ();
        qDebug () << "\nConsumer: " << tId;

        pthread_mutex_lock (&mutexVariable);

        if (sharedQueue.length () > 0) {
            for (int u = 0; u < sharedQueue.length (); u++) {
                sharedQueue.pop_front ();
                qDebug () << "\nRemoved by thread Consumer: " << tId << ", Length of queue is: " << sharedQueue.length ();
            }
        }
        else {
            pthread_cond_signal (&conditionVariable);
            qDebug () << "\nSignal issued by thread Consumer: " << tId << ", Length of queue is: " << sharedQueue.length ();
        }

        pthread_mutex_unlock (&mutexVariable);
    }   
    return NULL;
}

int main (int argc, char *argv[]) {
    numberOfActiveProducers = 2;
    numberOfActiveConsumers = 2;
    sizeOfSharedQueue       = 10;

    // Producer threads creation
    pthread_t producerA;
    pthread_t producerB;

    if (pthread_create (&producerA, NULL, producerThreadFunction, NULL)) {
        fprintf (stderr, "Error creating thread Producer A\n");
        return 1;
    }

    if (pthread_create (&producerB, NULL, producerThreadFunction, NULL)) {
        fprintf (stderr, "Error creating thread Producer B\n");
        return 1;
    }

    // Consumer threads creation
    pthread_t consumerA;
    pthread_t consumerB;

    if (pthread_create (&consumerA, NULL, consumerThreadFunction, NULL)) {
        fprintf (stderr, "Error creating thread Consumer A\n");
        return 1;
    }

    if (pthread_create (&consumerB, NULL, consumerThreadFunction, NULL)) {
        fprintf (stderr, "Error creating thread Consumer B\n");
        return 1;
    }

    // Joining every thread
    if (pthread_join (producerA, NULL)) {
        fprintf (stderr, "Error joining thread Producer A\n");
        return 2;
    }

    if (pthread_join (producerB, NULL)) {
        fprintf (stderr, "Error joining thread Producer B\n");
        return 2;
    }

    if (pthread_join (consumerB, NULL)) {
        fprintf (stderr, "Error joining thread Consumer B\n");
        return 2;
    }

    if (pthread_join (consumerA, NULL)) {
        fprintf (stderr, "Error joining thread Consumer A\n");
        return 2;
    }

    QApplication a (argc, argv);
    MainWindow w;
    w.show ();

    return a.exec ();
}

添加了带有std::cerr 的屏幕截图。输出没有区别:

【问题讨论】:

  • 你为什么要标记这个C?您似乎正在编写 Qt C++。
  • 我不知道qDebug() 做了什么。它是线程安全的吗?如果将其替换为 cout&lt;&lt; ... &lt;&lt; endl; 会发生什么?
  • 您提供的输出与您在此处引用的程序不匹配。此外,许多 pthread 调用没有检查任何错误。也就是说,为什么不使用 C++ 线程?
  • 根据他们的documentation,如果没有明确声明是线程安全的,那么函数不是。而qDebug() 对此一无所知。所以它是线程不安全的。所以可能发生的情况是一个调用覆盖了前一个调用的值,因为它可能在打印之前使用静态缓冲区。我认为,因此,您的行为未定义。
  • @I3x 我不能使用 std::cout。我今天试过了,但没有打印出来。使用 qDebug() 的功能是它自己打印该值。特别是在编写 QML 时,qDebug 是非常必要的,因为 cout 只在程序结束时打印。顺便说一句,这一次,当我停止程序时,它根本没有打印任何东西。这正是我尝试过的:while (1) { pthread_t tId = pthread_self (); //qDebug () &lt;&lt; "\nConsumer: " &lt;&lt; tId; std::cout &lt;&lt;"\nConsumerjjj: ";

标签: c++ multithreading pthreads producer-consumer


【解决方案1】:

在我的系统上,我确实看到了您期望的输出,开头是:

Producer:  0x700000081000 
Consumer:  0x700000187000 
Producer:  0x700000104000 
Consumer:  0x70000020a000 

但这只是运气,因为似乎不能保证 qDebug() 是线程安全的。一种解决方案可能是仅在您持有互斥锁时进行日志记录。或者使用不同的日志记录工具。请注意,写入std::cerr 是线程安全的,但如果您使用&lt;&lt; 写入多个令牌,您最终可能会遇到交错。所以你可以先格式化你的日志行,然后通过std::cerr.write()“原子地”编写它们。

【讨论】:

  • 查看问题中带有 std::cerr 的屏幕截图。现在该怎么办?
  • 好吧,我不确定,这对我来说没有多大意义。
猜你喜欢
  • 2012-10-13
  • 2017-02-01
  • 1970-01-01
  • 2020-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多