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 @ 2024-02-28 23:17  夕西行  阅读(891)  评论(0编辑  收藏  举报