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

Multithreading C+中的多线程生产者/消费者+;,multithreading,c++11,producer-consumer,Multithreading,C++11,Producer Consumer,我正在研究多线程,并编写了一个基本的生产者/消费者程序。我与生产商/消费者有两个问题,如下所述。1) 即使将消费者睡眠时间设置为低于生产者睡眠时间,生产者似乎仍能更快地执行。2) 在consumer中,当生产者完成添加到队列中,但队列中仍然有元素时,我复制了代码。有没有关于更好地构建代码的建议 #include <iostream> #include <queue> #include <mutex> class App { private: std:

我正在研究多线程,并编写了一个基本的生产者/消费者程序。我与生产商/消费者有两个问题,如下所述。1) 即使将消费者睡眠时间设置为低于生产者睡眠时间,生产者似乎仍能更快地执行。2) 在consumer中,当生产者完成添加到队列中,但队列中仍然有元素时,我复制了代码。有没有关于更好地构建代码的建议

#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;
}
#包括
#包括
#包括
类应用程序{
私人:
std::队列m_数据;
布尔姆·布菲完成;
std::mutex m_mutex;
int m_消费者睡眠;
国际生产商睡眠;
int m_队列大小;
公众:
应用程序(int和MaxQueue):m_bFinished(false)、m_ConsumerSleep(1)、m_ProducerSleep(5)、m_QueueSize(MaxQueue){}
无效生产者(){
对于(int i=0;istd::cout首先,您应该在使用者上使用条件变量而不是延迟。这样,使用者线程只有在队列不为空且生产者通知它时才会唤醒

也就是说,您的生产者调用更频繁的原因是生产者线程上的延迟。它是在保持互斥锁的同时执行的,因此消费者在延迟结束之前不会执行。您应该在调用
sleep\u for
之前释放互斥锁:

for(int i=0;i
主要方案:
生产者在锁定状态下推送值,并向条件变量发出信号

使用者在锁定条件变量下等待,并检查谓词以防止虚假唤醒

我的版本:

#include <iostream>
#include <queue>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <atomic>

class App {
private:
    std::queue<int> m_data;
    std::atomic_bool m_bFinished;
    std::mutex m_Mutex;
    std::condition_variable m_cv;
    int m_QueueSize;
public:
    App(int MaxQueue) 
        : m_bFinished(false)
        , m_QueueSize(MaxQueue) 
    {}

    void Producer()
    {
        for (int i = 0; i < m_QueueSize; ++i) 
        {
            {
                std::unique_lock<std::mutex> lock(m_Mutex);
                m_data.push(i); 
            }
            m_cv.notify_one();
            std::cout << "Producer Thread, queue size: " << m_data.size() << std::endl;
        }
        m_bFinished = true;
    }

    void Consumer() 
    {
        do
        {
            std::unique_lock<std::mutex> lock(m_Mutex);
            while (m_data.empty())
            {
                m_cv.wait(lock, [&](){ return !m_data.empty(); }); // predicate an while loop - protection from spurious wakeups
            }
            while(!m_data.empty()) // consume all elements from queue
            {
                std::cout << "Consumer Thread, queue element: " << m_data.front() << " size: " << m_data.size() << std::endl;
                m_data.pop();
            }
        } while(!m_bFinished);
    }
};


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;
}
#包括
#包括
#包括
#包括
#包括
#include for end标志,当您处理并发线程时,因为理论上,
m_bFinished
的值将存储在缓存线中,如果生产者线程中没有缓存失效,则可以从使用者线程中看不到更改的值。原子具有内存围栏,这保证了该值将是upda其他线程的ted


您也可以查看第页。

谢谢您的回答,睡眠的目的纯粹是模拟不同的处理延迟,而不是最终代码的一部分。