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实现)的更多相关文章

  1. 再谈多线程模型之生产者消费者(多生产者和单一消费者 )(c++11实现)

    0.关于 为缩短篇幅,本系列记录如下: 再谈多线程模型之生产者消费者(基础概念)(c++11实现) 再谈多线程模型之生产者消费者(单一生产者和单一消费者)(c++11实现) 再谈多线程模型之生产者消费 ...

  2. 再谈多线程模型之生产者消费者(单一生产者和多消费者 )(c++11实现)

    0.关于 为缩短篇幅,本系列记录如下: 再谈多线程模型之生产者消费者(基础概念)(c++11实现) 再谈多线程模型之生产者消费者(单一生产者和单一消费者)(c++11实现) 再谈多线程模型之生产者消费 ...

  3. 再谈多线程模型之生产者消费者(总结)(c++11实现)

    0.关于 为缩短篇幅,本系列记录如下: 再谈多线程模型之生产者消费者(基础概念)(c++11实现) 再谈多线程模型之生产者消费者(单一生产者和单一消费者)(c++11实现) 再谈多线程模型之生产者消费 ...

  4. 再谈多线程模型之生产者消费者(多生产者和多消费者 )(c++11实现)

    0.关于 为缩短篇幅,本系列记录如下: 再谈多线程模型之生产者消费者(基础概念)(c++11实现) 再谈多线程模型之生产者消费者(单一生产者和单一消费者)(c++11实现) 再谈多线程模型之生产者消费 ...

  5. 再谈多线程模型之生产者消费者(基础概念)(c++11实现)

    0.关于 为缩短篇幅,本系列记录如下: 再谈多线程模型之生产者消费者(基础概念)(c++11实现)[本文] 再谈多线程模型之生产者消费者(单一生产者和单一消费者)(c++11实现) 再谈多线程模型之生 ...

  6. Java 多线程基础(十二)生产者与消费者

    Java 多线程基础(十二)生产者与消费者 一.生产者与消费者模型 生产者与消费者问题是个非常典型的多线程问题,涉及到的对象包括“生产者”.“消费者”.“仓库”和“产品”.他们之间的关系如下: ①.生 ...

  7. Java 多线程详解(四)------生产者和消费者

    Java 多线程详解(一)------概念的引入:http://www.cnblogs.com/ysocean/p/6882988.html Java 多线程详解(二)------如何创建进程和线程: ...

  8. [Java基础] java多线程关于消费者和生产者

    多线程: 生产与消费 1.生产者Producer生产produce产品,并将产品放到库存inventory里:同时消费者Consumer从库存inventory里消费consume产品. 2.库存in ...

  9. Java多线程-同步:synchronized 和线程通信:生产者消费者模式

    大家伙周末愉快,小乐又来给大家献上技术大餐.上次是说到了Java多线程的创建和状态|乐字节,接下来,我们再来接着说Java多线程-同步:synchronized 和线程通信:生产者消费者模式. 一.同 ...

随机推荐

  1. SUNTANS 及 FVCOM 对流扩散方程求解简介[TBC]

    最近接到一个任务,就是解决FVCOM中对流扩散计算不守衡问题.导师认为是其求解时候水平和垂向计算分开求解所导致的,目前我也没搞清到底有什么问题,反正就是让把SUNTANS的对流扩散计算挪到FVCOM中 ...

  2. nginx_access_log的格式设置

    log_format <NAME> <Strin­­­g>; 关键字 格式标签 日志格式 关键字:其中关键字error_log不能改变 格式标签:格式标签是给一套日志格式设置一 ...

  3. JForum论坛安装以及部署

    转载链接:https://blog.csdn.net/jhyfugug/article/details/79467369 首先安装JForum之前,先准备好安装环境Windows7+JDK+Tomca ...

  4. OAuth2.0实战!使用JWT令牌认证!

    大家好,我是不才陈某~ 这是<Spring Security 进阶>的第3篇文章,往期文章如下: 实战!Spring Boot Security+JWT前后端分离架构登录认证! 妹子始终没 ...

  5. C语言之内核中的struct list_head 结构体

    以下地址文章解释很好 http://blog.chinaunix.net/uid-27122224-id-3277511.html 对下面的结构体分析 1 struct person 2 { 3 in ...

  6. Zookeeper之创建组,加入组,列出组成员和删除组

    public class CreateGroup implements Watcher { private static final int SESSION_TIMEOUT=5000; //ZooKe ...

  7. Android 开源框架Universal-Image-Loader加载https图片

    解决方案就是 需要 android https HttpsURLConnection 这个类忽略证书 1,找到 Universal-Image-Loader的library依赖包下面com.nostr ...

  8. Linux学习 - 文本编辑器Vim

    一.Vim工作模式 二.命令 插入 a 光标后插入 A 光标所在行尾插入 i 光标前插入 I 光标所在行首插入 o 光标下插入新行 O 光标上插入新行   删除 x 删除光标处字符 nx 删除光标处后 ...

  9. 访问网页全过程,用wireshark抓包分析

    用wireshark抓包查看访问网站过程 打开wireshark,打开一个无痕浏览器,输入网址,到网页呈现这一过程,网络数据包传递的消息都会被放在wireshark里.针对这些包,我们可以逐一分析,摸 ...

  10. Java高精度基础+开根

    在焦作站的acm网络赛中遇到了一个高精度开根的水题--但是那时候WA了 后面学写java补题还T了orz 所以写一篇文章来记录一下java的大整数类型的基础和开根还有一点心得体会吧 首先给那一题的题面 ...