c++ queue在多线程中的使用,生产者、消费者,锁,条件变量

queue队列,先进先出。

多线程的一种使用案例:

生产者每3s push一个元素,消费者每5s才能 pop一个元素(队首),那么2个消费者就可以及时地消耗掉push的元素。

复制代码
#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<queue>

std::queue<int> m_queue;
std::mutex m_mutex;
std::condition_variable m_cv_notEmpty, m_cv_notFull;

void funcIn()
{
    int nMax = 2;
    int i = 0;
    while (true)
    {
        std::this_thread::sleep_for(std::chrono::seconds(3));

        std::unique_lock<std::mutex> lck(m_mutex);
        while (m_queue.size()==nMax)    //如果队列满,不再push
        {
            std::cout << "队列已满" << std::endl;
            m_cv_notFull.wait(lck);        //当前线程被阻塞,直到收到notify为止
        }
        m_queue.push(i);
        lck.unlock();                    //解锁互斥量
        m_cv_notEmpty.notify_all();

        std::cout << "\t" << i << std::endl;
        i++;
    }
}

void funcOut()
{
    while (true)
    {
        std::this_thread::sleep_for(std::chrono::seconds(5));

        std::unique_lock<std::mutex> lck(m_mutex);
        while (m_queue.empty())            //如果队列空,不再pop
        {
            std::cout << "队列为空" << std::endl;
            m_cv_notEmpty.wait(lck);    //当前线程被阻塞,直到收到notify为止
        }
        std::cout << m_queue.front() << std::endl;
        m_queue.pop();

        lck.unlock();                    //解锁互斥量
        m_cv_notFull.notify_all();
    }
}

int main()
{
    std::thread producer(funcIn);
    std::thread consumer1(funcOut);
    std::thread consumer2(funcOut);

    producer.join();
    consumer1.join();
    consumer2.join();
    return 0;
}
复制代码

如果需要push多个,可以使用struct

复制代码
#include<iostream>
#include<thread>
#include<mutex>
#include<queue>

struct Data
{
    int i = 0;
    int j = 0;
};

std::queue<Data> m_queue;
std::mutex m_mutex;
std::condition_variable _not_empty;

void funcIn()
{
    int i = 0;
    Data data;
    while (true)
    {
        std::this_thread::sleep_for(std::chrono::seconds(3));
        std::cout << "\t" << i << std::endl;
        std::unique_lock<std::mutex> lck(m_mutex);
        data.i = i;
        m_queue.push(data);
        _not_empty.notify_one();

        i++;
    }
}

void funcOut()
{
    int i = -1;
    Data data;
    while (true)
    {
        std::this_thread::sleep_for(std::chrono::seconds(5));

        std::unique_lock<std::mutex> lck(m_mutex);
        _not_empty.wait(lck, [](){
            return !m_queue.empty();
            });
        data= m_queue.front();
        m_queue.pop();
        std::cout << data.i<<" "<<data.j << std::endl;
    }
}

int main()
{
    std::thread producer(funcIn);
    std::thread consumer1(funcOut);
    std::thread consumer2(funcOut);

    producer.join();
    consumer1.join();
    consumer2.join();

    return 0;
}
复制代码

当然,可以直接使用大牛实现的多线程的队列 concurrentqueue、blockingconcurrentqueue

GitHub - cameron314/concurrentqueue: A fast multi-producer, multi-consumer lock-free concurrent queue for C++11

只需要将下图3个头文件放入工程目录即可

不再需要自己加锁、条件等待,可读性较高。

复制代码
#include <iostream>
#include<thread>
#include"blockingconcurrentqueue.h"

moodycamel::BlockingConcurrentQueue<int> m_queue;

void funcIn()
{
    int i = 0;
    while (true)
    {
        std::this_thread::sleep_for(std::chrono::seconds(3));
        m_queue.try_enqueue(i);    
        std::cout << "\t" << i << std::endl;

        i++;
    }
}

void funcOut()
{
    int i = -1;
    while (true)
    {
        std::this_thread::sleep_for(std::chrono::seconds(5));        
        m_queue.wait_dequeue(i);
        std::cout << i << std::endl;
    }
}
复制代码

 

posted @   夕西行  阅读(1076)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
历史上的今天:
2020-02-28 SVM参数设置总结(参考源码ml.hpp)
2020-02-28 机器学习总结(参考源码ml.hpp)
2020-02-28 SVM的使用train()
点击右上角即可分享
微信分享提示