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
只需要将下图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; } }