再谈多线程模型之生产者消费者(单一生产者和单一消费者)(c++11实现)
0.关于
为缩短篇幅,本系列记录如下:
再谈多线程模型之生产者消费者(基础概念)(c++11实现)
再谈多线程模型之生产者消费者(单一生产者和单一消费者)(c++11实现)【本文】
再谈多线程模型之生产者消费者(单一生产者和多消费者)(c++11实现)
再谈多线程模型之生产者消费者(多生产者和单一消费者 )(c++11实现)
再谈多线程模型之生产者消费者(多生产者和多消费者 )(c++11实现)
再谈多线程模型之生产者消费者(总结)(c++11实现)
本文涉及到的代码演示环境: VS2017
欢迎留言指正
1.单一生产者 & 单一消费者
- 1.1 因为只有单一的生产者和消费者,所以,同步的也只有他们俩,互斥仅仅存在消费者和生产者之间,生产者(消费者)之间不存在互斥?一个对象怎么谈互斥?自己与自己互斥? 显然,这是一个假命题。所以,这个模型中,互斥只存在生产者与消费者。
- 1.2 一个结构帮你了解,
struct repo_
{
// 用作互斥访问缓冲区
std::mutex _mtx_queue;
// 缓冲区最大size
unsigned int _count_max_queue_10 = 10;
// 缓冲区
std::queue<int> _queue;
// 缓冲区没有满,通知生产者继续生产
std::condition_variable _cv_queue_not_full;
// 缓冲区不为空,通知消费者继续消费
std::condition_variable _cv_queue_not_empty;
repo_(const unsigned int count_max_queue = 10) :_count_max_queue_10(count_max_queue) {}
};
- 1.3 生产者流程: 1.等待缓冲区没有满信号,2.生产数据放入缓冲区,3.通知消费者可以取数据。
template <typename T>
void thread_produce_item(const int &thread_index, repo<T>& param_repo, const T& repo_item)
{
std::unique_lock<std::mutex> lock(param_repo._mtx_queue);
// 1. 生产者只要发现缓冲区没有满, 就继续生产
param_repo._cv_queue_not_full.wait(lock, [&] { return param_repo._queue.size() < param_repo._count_max_queue_10; });
// 2. 将生产好的商品放入缓冲区
param_repo._queue.push(repo_item);
// log to console
std::cout << "生产者" << thread_index << "生产数据:" << repo_item << "\n";
// 3. 通知消费者可以消费了
param_repo._cv_queue_not_empty.notify_one();
}
- 1.4 消费者流程: 1.等待缓冲区不为空信号,2.从缓冲区中消费数据,3.通知生产者继续生产数据。
template <typename T>
T thread_consume_item(const int thread_index, repo<T>& param_repo)
{
std::unique_lock<std::mutex> lock(param_repo._mtx_queue);
// 1. 消费者需要等待【缓冲区不为空】的信号
param_repo._cv_queue_not_empty.wait(lock, [&] {return !param_repo._queue.empty(); });
// 2. 拿出数据
T item;
item = param_repo._queue.front();
param_repo._queue.pop();
std::cout << "消费者" << thread_index << "从缓冲区中拿出一组数据:" << item << std::endl;
// 3. 通知生产者,继续生产
param_repo._cv_queue_not_full.notify_one();
return item;
}
- 1.5 完整源码
#pragma once
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <vector>
std::mutex _mtx;
std::condition_variable _cv_not_full;
std::condition_variable _cv_not_empty;
const int max_queue_size_10 = 10;
template<typename T>
struct repo_
{
// 用作互斥访问缓冲区
std::mutex _mtx_queue;
// 缓冲区最大size
unsigned int _count_max_queue_10 = 10;
// 缓冲区
std::queue<T> _queue;
// 缓冲区没有满,通知生产者继续生产
std::condition_variable _cv_queue_not_full;
// 缓冲区不为空,通知消费者继续消费
std::condition_variable _cv_queue_not_empty;
repo_(const unsigned int count_max_queue = 10) :_count_max_queue_10(count_max_queue) {}
};
template <typename T>
using repo = repo_<T>;
//----------------------------------------------------------------------------------------
// 生产者生产数据
template <typename T>
void thread_produce_item(const int &thread_index, repo<T>& param_repo, const T& repo_item)
{
std::unique_lock<std::mutex> lock(param_repo._mtx_queue);
// 1. 生产者只要发现缓冲区没有满, 就继续生产
param_repo._cv_queue_not_full.wait(lock, [&] { return param_repo._queue.size() < param_repo._count_max_queue_10; });
// 2. 将生产好的商品放入缓冲区
param_repo._queue.push(repo_item);
// log to console
std::cout << "生产者" << thread_index << "生产数据:" << repo_item << "\n";
// 3. 通知消费者可以消费了
param_repo._cv_queue_not_empty.notify_one();
}
//----------------------------------------------------------------------------------------
// 消费者消费数据
template <typename T>
T thread_consume_item(const int thread_index, repo<T>& param_repo)
{
std::unique_lock<std::mutex> lock(param_repo._mtx_queue);
// 1. 消费者需要等待【缓冲区不为空】的信号
param_repo._cv_queue_not_empty.wait(lock, [&] {return !param_repo._queue.empty(); });
// 2. 拿出数据
T item;
item = param_repo._queue.front();
param_repo._queue.pop();
std::cout << "消费者" << thread_index << "从缓冲区中拿出一组数据:" << item << std::endl;
// 3. 通知生产者,继续生产
param_repo._cv_queue_not_full.notify_one();
return item;
}
//----------------------------------------------------------------------------------------
/**
* @ brief: 生产者线程
* @ thread_index - 线程标识,区分是哪一个线程
* @ count_max_produce - 最大生产次数
* @ param_repo - 缓冲区
* @ return - void
*/
template< typename T >
void thread_pro(const int thread_index, const int count_max_produce, repo<T>* param_repo)
{
for (int item = 0; item < count_max_produce; ++item)
{
thread_produce_item<T>(thread_index, *param_repo, item);
std::this_thread::sleep_for(std::chrono::microseconds(16));
}
}
/**
* @ brief: 消费者线程
* @ thread_index - 线程标识,区分线程
* @ param_repo - 缓冲区
* @ return - void
*/
template< typename T >
void thread_con(const int thread_index, repo<T>* param_repo)
{
while (true)
{
T item;
item = thread_consume_item<T>(thread_index, *param_repo);
std::this_thread::sleep_for(std::chrono::microseconds(16));
if ((param_repo->_count_max_queue_10 - 1) == item)
break;
}
}
// 入口函数
//----------------------------------------------------------------------------------------
int main(int argc, char *argv[], char *env[])
{
// 缓冲区
repo<int> repository;
// 线程池
std::vector<std::thread> vec_thread;
// 生产者
vec_thread.push_back(std::thread(thread_pro<int>, 1, 10, &repository));
// 消费者
vec_thread.push_back(std::thread(thread_con<int>, 1, &repository));
for (auto &item : vec_thread)
{
item.join();
}
return 0;
}
- 1.6 可能输出结果

再谈多线程模型之生产者消费者(单一生产者和单一消费者)(c++11实现)的更多相关文章
- 再谈多线程模型之生产者消费者(多生产者和单一消费者 )(c++11实现)
0.关于 为缩短篇幅,本系列记录如下: 再谈多线程模型之生产者消费者(基础概念)(c++11实现) 再谈多线程模型之生产者消费者(单一生产者和单一消费者)(c++11实现) 再谈多线程模型之生产者消费 ...
- 再谈多线程模型之生产者消费者(单一生产者和多消费者 )(c++11实现)
0.关于 为缩短篇幅,本系列记录如下: 再谈多线程模型之生产者消费者(基础概念)(c++11实现) 再谈多线程模型之生产者消费者(单一生产者和单一消费者)(c++11实现) 再谈多线程模型之生产者消费 ...
- 再谈多线程模型之生产者消费者(总结)(c++11实现)
0.关于 为缩短篇幅,本系列记录如下: 再谈多线程模型之生产者消费者(基础概念)(c++11实现) 再谈多线程模型之生产者消费者(单一生产者和单一消费者)(c++11实现) 再谈多线程模型之生产者消费 ...
- 再谈多线程模型之生产者消费者(多生产者和多消费者 )(c++11实现)
0.关于 为缩短篇幅,本系列记录如下: 再谈多线程模型之生产者消费者(基础概念)(c++11实现) 再谈多线程模型之生产者消费者(单一生产者和单一消费者)(c++11实现) 再谈多线程模型之生产者消费 ...
- 再谈多线程模型之生产者消费者(基础概念)(c++11实现)
0.关于 为缩短篇幅,本系列记录如下: 再谈多线程模型之生产者消费者(基础概念)(c++11实现)[本文] 再谈多线程模型之生产者消费者(单一生产者和单一消费者)(c++11实现) 再谈多线程模型之生 ...
- Java 多线程基础(十二)生产者与消费者
Java 多线程基础(十二)生产者与消费者 一.生产者与消费者模型 生产者与消费者问题是个非常典型的多线程问题,涉及到的对象包括“生产者”.“消费者”.“仓库”和“产品”.他们之间的关系如下: ①.生 ...
- Java 多线程详解(四)------生产者和消费者
Java 多线程详解(一)------概念的引入:http://www.cnblogs.com/ysocean/p/6882988.html Java 多线程详解(二)------如何创建进程和线程: ...
- [Java基础] java多线程关于消费者和生产者
多线程: 生产与消费 1.生产者Producer生产produce产品,并将产品放到库存inventory里:同时消费者Consumer从库存inventory里消费consume产品. 2.库存in ...
- Java多线程-同步:synchronized 和线程通信:生产者消费者模式
大家伙周末愉快,小乐又来给大家献上技术大餐.上次是说到了Java多线程的创建和状态|乐字节,接下来,我们再来接着说Java多线程-同步:synchronized 和线程通信:生产者消费者模式. 一.同 ...
随机推荐
- NCBI SRA数据如何进行md5校验?
下了一些sra数据库中的公共数据,因为pretech和aspera不稳定,稍微大点的文件经常传断,部分文件我只能通过本地下载再上传. 那么问题来了,sra没有md5校验,我怎么知道我数据的完整性,尤其 ...
- Dango之form校验组件
目录 1.引入案例 2. form组件的功能 3. form组件的使用 3.1 自定义form校验类 3.2 校验数据 3.3 渲染页面 3.4 展示错误信息 3.5 自定义校验结果 3.6 form ...
- acclaim
欲学acclaim,先学claim.即使学会claim,未必记住acclaim. [LDOCE] claim的词源是cry out, shoutverb:1. state that sth is tr ...
- Hadoop 相关知识点(一)
作业提交流程(MR执行过程) Mapreduce2.x Client:用来提交作业 ResourceManager:协调集群上的计算资源的分配 NodeManager:负责启动和监控集群上的计算容器( ...
- Scala(三)【函数式编程】
目录 一.方法和函数 1.方法 1)基本语法 2)简化原则 3)方法参数 2.函数 3.方法和函数的区别 二.高阶函数 三.匿名函数 四.柯里化 五.闭包 一.方法和函数 1.方法 1)基本语法 de ...
- Linux学习 - ifconfig
ifconfig 1.功能 用来查看和配置网络设备,当网络环境发生改变时可通过此命令对网络进行相应的配置. 2.用法 ifconfig [网络设备] [参数] (1).参数 up 启动指定网络设备 ...
- Can references refer to invalid location in C++?
在C++中,引用比指针更加的安全,一方面是因为引用咋定义时必须进行初始化,另一方面是引用一旦被初始化就无法使其与其他对象相关联. 但是,在使用引用的地方仍然会有一些例外. (1)Reference t ...
- Linux shell实现每天定时备份mysql数据库
每天定时备份mysql数据库任务,删除指定天数前的数据,保留指定天的数据: 需求: 1,每天4点备份mysql数据: 2,为节省空间,删除超过3个月的所有备份数据: 3,删除超过7天的备份数据,保留3 ...
- 侵入式&非侵入式
侵入式设计 引入了框架,对现有的类的结构有影响:即需要实现或继承某些特定类. 例如:Struts框架 非侵入式设计 引入了框架,对现有的类结构没有影响. 例如:Hibernate框架 / Spring ...
- 【HarmonyOS】【DevEco Studio】NOTE04:How to Jump to a Page(页面间的跳转)
页面创建与基本设置 创建页面 创建两个新页面,分别为AbilityPage1.AbilityPage2 设置页面基本内容 以AbilityPage1为例 导包 import com.example.m ...