用BlockBoundQueue和c++11实现多线程生产者消费者问题
来源:互联网 发布:淘宝如何取消超级推广 编辑:程序博客网 时间:2024/05/18 10:00
最近在读到陈硕的《linux多线程服务端编程》这书时,发现了两个特别好用的模板类 : BlockQueue和BlockBoundQueue,用来实现多线程中的生产者消费者问题是特别方便的。但是其源码中用到boost库,所以在这里我稍微修改下,实现如下。
这里只写出BlockBoundQueue,读者可自行写出BlockQueue
// file : blockBoundQueue.h#ifndef YANG_BLOCKBOUNDQUEUE#define YANG_BLOCKBOUNDQUEUE#include <mutex>#include <condition_variable>#include <queue>#include <cstdio>namespace yang{#define _FULL 4 //template <typename _Tp>class BlockBoundQueue{public: BlockBoundQueue(size_t bound = _FULL) :bound_(bound){} BlockBoundQueue(const BlockBoundQueue&) = delete; BlockBoundQueue& operator=(const BlockBoundQueue&) = delete; void push(const _Tp& value) { std::unique_lock<std::mutex> lck(mutex_);// 利用RAII技法,将mutex_托管给lck while (count_ + 1 == bound_)// 用while防止虚假唤醒 { printf("the queue is full , waiting for the consumer consuming !\n"); notFull_.wait(lck); //等待队列非满条件发生 } count_++; queue_.push(value); notEmpty_.notify_one();//通知队列非空,不能用all,读者自行思考为什么 } _Tp get() { std::unique_lock<std::mutex> lck(mutex_); while (queue_.empty()) { printf("the queue is empty , waiting for the producer producing !\n"); notEmpty_.wait(lck);//等待队列为非空 } _Tp front(queue_.front()); queue_.pop(); count_--; notFull_.notify_one();//通知队列为非满,请注意不能用all return front; }private: std::mutex mutex_; std::condition_variable notEmpty_; std::condition_variable notFull_; std::queue<_Tp> queue_; size_t count_{ 0 }; size_t bound_;};}#endif//在visual studio 2013上编译运行通过
分析上面代码,首先std::queue
容器并没有提供full()
这个成员函数,所以我们要自己维护一个size_t type
的变量count_
,并初始化为0 。其次,我们要禁用掉拷贝构造和赋值函数,只保留构造函数即可。最重要的两个成员函数是push()
和get()
,在这里每次进入这两个函数之后,先加锁,这里我们用到了RAII的技法来保证我们的加锁操作是异常安全的,并且通过两个条件变量notEmpty 和 notFull
的配合,实现了线程安全的出队和入队操作。
下面我们来实现下,篇幅的原因,直接上多生产者多消费者模式,因为其他的几种都是它的特列。
// file : main.cpp#include <cstdio>#include <cstdlib>#include <thread>#include "BlockBoundQueue.h"yang::BlockBoundQueue<int> blockboundqueue_;// 全局的缓冲边界队列const int total = 16; // 商品总数void consumer(size_t id,size_t n); // 消费者void producer(size_t id,size_t n); // 生产者int main(){ std::thread consumer1(consumer,0, 5); std::thread consumer2(consumer,1, 5); std::thread consumer3(consumer,2, 6); std::thread producer1(producer,0, 8); std::thread producer2(producer,1, 8); consumer1.join(); consumer2.join(); consumer3.join(); producer1.join(); producer2.join(); system("pause"); return 0;}void consumer(size_t id,size_t n){ for (auto i = 0; i < n; ++i) { std::this_thread::sleep_for(std::chrono::seconds(2)); int item = blockboundqueue_.get(); printf("the %d^th consumer thread has consumed the %d^th item\n", id,item); }}void producer(size_t id,size_t n){ for (int i = 0; i < n; ++i) { blockboundqueue_.push(i); printf("the %d^th producer thread has produced the %d^th item\n",id, i); }}
执行结果如下:
总结 : 利用BlockBoundQueue可以很方便的实现生产者消费者模式,并且其本身实现起来简洁优雅,我们应该学会使用。
参考资料:
Linux多线程服务端编程 陈硕著
http://www.cplusplus.com/reference/
https://baptiste-wicht.com/posts/2012/04/c11-concurrency-tutorial-advanced-locking-and-condition-variables.html
http://www.cnblogs.com/haippy/p/3236136.html
- 用BlockBoundQueue和c++11实现多线程生产者消费者问题
- 生产者消费者问题 伪代码和C语言多线程实现
- 用java实现生产者和消费者问题
- 用java实现生产者和消费者问题
- java实现 生产者和消费者问题 多线程同步示例
- 关于Java多线程实现生产者和消费者的问题
- 用多线程实现“生产者-消费者问题”(代码+实验报告)
- 用JAVA实现多线程(生产者与消费者问题)
- .net实现--多线程之生产者/消费者问题
- 生产者消费者问题(Linux多线程下两种实现)
- JAVA多线程实现生产者消费者问题
- Boost多线程实现生产者与消费者问题
- java使用多线程实现生产者消费者问题
- Java多线程模拟实现消费者生产者问题
- java代码实现多线程消费者生产者问题。
- 操作系统 使用C语言实现生产者和消费者问题
- 生产者消费者问题--多线程
- 多线程--生产者消费者问题
- ROS导航功能包集中的修复机制
- SAP HANA查找字符串位置
- vs2013+ 编译 opencv3.x 的拓展包
- 随机输出带权重数组中的值(百度二面算法题目)
- Python 数据分析 pandas
- 用BlockBoundQueue和c++11实现多线程生产者消费者问题
- selectionSort
- maven-webserver插件
- 简单猜数字游戏
- Win 10 配置自动更新策略
- 挖掘模式(上)
- PS_BaseUse_颜色替换
- css float的代码顺序和html页面显示顺序的问题
- 摄像机标定学习笔记(3)