C ++中的多线程生产者/消费者

问题描述 投票:0回答:2

我正在研究多线程并编写了基本的生产者/消费者。我在下面写的生产者/消费者有两个问题。 1)即使将消费者的睡眠时间设置为低于生产者的睡眠时间,生产者似乎仍然可以更快地执行。 2)在生产者完成添加到队列的情况下,在使用者中我复制了代码,但是队列中仍然有元素。有什么建议可以更好地构造代码吗?

#include <iostream>
#include <queue>
#include <mutex>

class App {
private:
    std::queue<int> m_data;
    bool m_bFinished;
    std::mutex m_Mutex;
    int m_ConsumerSleep;
    int m_ProducerSleep;
    int m_QueueSize;
public:
    App(int &MaxQueue) :m_bFinished(false), m_ConsumerSleep(1), m_ProducerSleep(5), m_QueueSize(MaxQueue){}
    void Producer() {

        for (int i = 0; i < m_QueueSize; ++i) {
            std::lock_guard<std::mutex> guard(m_Mutex);
            m_data.push(i); 
            std::cout << "Producer Thread, queue size: " << m_data.size() << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(m_ProducerSleep));
        }
        m_bFinished = true;
    }

    void Consumer() {
        while (!m_bFinished) {
            if (m_data.size() > 0) {
                std::lock_guard<std::mutex> guard(m_Mutex);
                std::cout << "Consumer Thread, queue element: " << m_data.front() << " size: " << m_data.size() << std::endl;
                m_data.pop();
            }
            else {
                std::cout << "No elements, skipping" << std::endl;
            }
            std::this_thread::sleep_for(std::chrono::seconds(m_ConsumerSleep));
        }
        while (m_data.size() > 0) {
            std::lock_guard<std::mutex> guard(m_Mutex);
            std::cout << "Emptying remaining elements " << m_data.front() << std::endl;
            m_data.pop();
            std::this_thread::sleep_for(std::chrono::seconds(m_ConsumerSleep));
        }
    }

};


int main()
{
    int QueueElements = 10;
    App app(QueueElements);
    std::thread consumer_thread(&App::Consumer, &app);
    std::thread producer_thread(&App::Producer, &app);

    producer_thread.join();
    consumer_thread.join();


    std::cout << "loop exited" << std::endl;
    return 0;
}
multithreading c++11 producer-consumer
2个回答
1
投票

首先,您应该使用条件变量,而不是对使用者造成延迟。这样,使用者线程仅在队列不为空且生产者通知时唤醒。

也就是说,您的生产者调用更加频繁的原因是生产者线程上的延迟。它在保持互斥锁的同时执行,因此使用者直到延迟结束后才执行。您应在调用sleep_for之前释放互斥锁:

for (int i = 0; i < m_QueueSize; ++i) {
            /* Introduce a scope to release the mutex before sleeping*/
            {
               std::lock_guard<std::mutex> guard(m_Mutex);
                m_data.push(i); 
                std::cout << "Producer Thread, queue size: " << m_data.size() << std::endl;
            } // Mutex is released here
            std::this_thread::sleep_for(std::chrono::seconds(m_ProducerSleep));
        }

0
投票

您应使用condition_variable。不要对线程使用睡眠。

© www.soinside.com 2019 - 2024. All rights reserved.