代码都类似,看懂一个,基本都能理解了。

共有代码:

#include <cstdlib>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>

static const int kItemRepositorySize = 10; // Item buffer size.
static const int kItemsToProduce = 1000;   // How many items we plan to produce.
std::mutex mutex;//多线程标准输出同步锁

单生产者单消费者模式:

 struct ItemRepository
{
int item_buffer[kItemRepositorySize]; // 产品缓冲区, 配合 read_position 和 write_position 模型环形队列.
size_t read_position; // 消费者读取产品位置.
size_t write_position; // 生产者写入产品位置.
std::mutex mtx; // 互斥量,保护产品缓冲区
std::condition_variable repo_not_full; // 条件变量, 指示产品缓冲区不为满.
std::condition_variable repo_not_empty; // 条件变量, 指示产品缓冲区不为空.
} gItemRepository; // 产品库全局变量, 生产者和消费者操作该变量. typedef struct ItemRepository ItemRepository; void ProduceItem(ItemRepository * ir, int item)
{
std::unique_lock<std::mutex> lock(ir->mtx);
while (((ir->write_position + ) % kItemRepositorySize)
== ir->read_position)
{ // item buffer is full, just wait here.
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "缓冲区满,等待缓冲区不满\n";
}
(ir->repo_not_full).wait(lock); // 生产者等待"产品库缓冲区不为满"这一条件发生.
} (ir->item_buffer)[ir->write_position] = item; // 写入产品.
(ir->write_position)++; // 写入位置后移. if (ir->write_position == kItemRepositorySize) // 写入位置若是在队列最后则重新设置为初始位置.
ir->write_position = ; (ir->repo_not_empty).notify_all(); // 通知消费者产品库不为空.
lock.unlock(); // 解锁.
} int ConsumeItem(ItemRepository *ir)
{
int data;
std::unique_lock<std::mutex> lock(ir->mtx);
// item buffer is empty, just wait here.
while (ir->write_position == ir->read_position)
{
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "缓冲区空,等待生产者生成产品\n";
}
(ir->repo_not_empty).wait(lock); // 消费者等待"产品库缓冲区不为空"这一条件发生.
} data = (ir->item_buffer)[ir->read_position]; // 读取某一产品
(ir->read_position)++; // 读取位置后移 if (ir->read_position >= kItemRepositorySize) // 读取位置若移到最后,则重新置位.
ir->read_position = ; (ir->repo_not_full).notify_all(); // 通知消费者产品库不为满.
lock.unlock(); // 解锁. return data; // 返回产品.
} void ProducerTask() // 生产者任务
{
for (int i = ; i <= kItemsToProduce; ++i)
{
// sleep(1);
ProduceItem(&gItemRepository, i); // 循环生产 kItemsToProduce 个产品.
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "生产第 " << i << "个产品" << std::endl;
}
}
} void ConsumerTask() // 消费者任务
{
static int cnt = ;
while ()
{
std::this_thread::sleep_for(std::chrono::seconds());
int item = ConsumeItem(&gItemRepository); // 消费一个产品.
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "消费第" << item << "个产品" << std::endl;
}
if (++cnt == kItemsToProduce) break; // 如果产品消费个数为 kItemsToProduce, 则退出.
}
} void InitItemRepository(ItemRepository *ir)
{
ir->write_position = ; // 初始化产品写入位置.
ir->read_position = ; // 初始化产品读取位置.
} void test()
{
InitItemRepository(&gItemRepository);
std::thread producer(ProducerTask); // 创建生产者线程.
std::thread consumer(ConsumerTask); // 创建消费之线程. producer.join();
consumer.join();
}

单生产者多消费者模式:

 struct ItemRepository
{
int item_buffer[kItemRepositorySize];
size_t read_position;
size_t write_position;
size_t item_counter;
std::mutex mtx;
std::mutex item_counter_mtx;
std::condition_variable repo_not_full;
std::condition_variable repo_not_empty;
} gItemRepository; typedef struct ItemRepository ItemRepository; void ProduceItem(ItemRepository *ir, int item)
{
std::unique_lock<std::mutex> lock(ir->mtx);
while (((ir->write_position + ) % kItemRepositorySize)
== ir->read_position)
{
// item buffer is full, just wait here.
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "缓冲区满,等待缓冲区不满\n";
}
(ir->repo_not_full).wait(lock);
} (ir->item_buffer)[ir->write_position] = item;
(ir->write_position)++; if (ir->write_position == kItemRepositorySize)
ir->write_position = ; (ir->repo_not_empty).notify_all();
lock.unlock();
} int ConsumeItem(ItemRepository *ir)
{
int data;
std::unique_lock<std::mutex> lock(ir->mtx);
// item buffer is empty, just wait here.
while (ir->write_position == ir->read_position)
{
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "缓冲区空,等待生产者生产产品\n";
}
(ir->repo_not_empty).wait(lock);
} data = (ir->item_buffer)[ir->read_position];
(ir->read_position)++; if (ir->read_position >= kItemRepositorySize)
ir->read_position = ; (ir->repo_not_full).notify_all();
lock.unlock(); return data;
} void ProducerTask()
{
for (int i = ; i <= kItemsToProduce; ++i)
{
std::this_thread::sleep_for(std::chrono::milliseconds());
ProduceItem(&gItemRepository, i);
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "生产线程" << std::this_thread::get_id()
<< "生产第" << i << "个产品" << std::endl;
}
}
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "生产线程" << std::this_thread::get_id()
<< "退出" << std::endl;
}
} void ConsumerTask()
{
bool ready_to_exit = false;
while ()
{
// std::this_thread::sleep_for(std::chrono::milliseconds(6));
std::unique_lock<std::mutex> lock(gItemRepository.item_counter_mtx);
if (gItemRepository.item_counter < kItemsToProduce)
{
int item = ConsumeItem(&gItemRepository);
++(gItemRepository.item_counter);
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "消费线程" << std::this_thread::get_id()
<< "正在消费第" << item << "个产品" << std::endl;
}
}
else
{
ready_to_exit = true;
}
lock.unlock(); if (ready_to_exit == true)
{
break;
}
}
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "消费线程" << std::this_thread::get_id()
<< "退出" << std::endl;
}
} void InitItemRepository(ItemRepository *ir)
{
ir->write_position = ;
ir->read_position = ;
ir->item_counter = ;
} void test()
{
InitItemRepository(&gItemRepository);
std::thread producer(ProducerTask);
std::thread consumer1(ConsumerTask);
std::thread consumer2(ConsumerTask);
std::thread consumer3(ConsumerTask);
std::thread consumer4(ConsumerTask); producer.join();
consumer1.join();
consumer2.join();
consumer3.join();
consumer4.join();
}

多消费者单生产者模式:

 struct ItemRepository
{
int item_buffer[kItemRepositorySize];
size_t read_position;
size_t write_position;
size_t item_counter;
std::mutex mtx;
std::mutex item_counter_mtx;
std::condition_variable repo_not_full;
std::condition_variable repo_not_empty;
} gItemRepository; typedef struct ItemRepository ItemRepository; void ProduceItem(ItemRepository *ir, int item)
{
std::unique_lock<std::mutex> lock(ir->mtx);
while (((ir->write_position + ) % kItemRepositorySize)
== ir->read_position)
{
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "缓冲区满,等待缓冲区不满\n";
}
(ir->repo_not_full).wait(lock);
} (ir->item_buffer)[ir->write_position] = item;
(ir->write_position)++; if (ir->write_position == kItemRepositorySize)
ir->write_position = ; (ir->repo_not_empty).notify_all();
lock.unlock();
} int ConsumeItem(ItemRepository *ir)
{
int data;
std::unique_lock<std::mutex> lock(ir->mtx);
// item buffer is empty, just wait here.
while (ir->write_position == ir->read_position)
{
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "消费者等待产品中。。。\n";
}
(ir->repo_not_empty).wait(lock);
} data = (ir->item_buffer)[ir->read_position];
(ir->read_position)++; if (ir->read_position >= kItemRepositorySize)
ir->read_position = ; (ir->repo_not_full).notify_all();
lock.unlock(); return data;
} void ProducerTask()
{
bool ready_to_exit = false;
while ()
{
std::this_thread::sleep_for(std::chrono::milliseconds());
std::unique_lock<std::mutex> lock(gItemRepository.item_counter_mtx);
if (gItemRepository.item_counter < kItemsToProduce)
{
++(gItemRepository.item_counter);
ProduceItem(&gItemRepository, gItemRepository.item_counter);
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "消费者" << std::this_thread::get_id()
<< "正在生产第" << gItemRepository.item_counter
<< "个产品" << std::endl;
}
}
else
{
ready_to_exit = true;
}
lock.unlock();
if (ready_to_exit == true) break;
}
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "消费者" << std::this_thread::get_id()
<< "退出" << std::endl;
}
} void ConsumerTask()
{
static int item_consumed = ;
while ()
{
std::this_thread::sleep_for(std::chrono::milliseconds());
++item_consumed;
if (item_consumed <= kItemsToProduce)
{
int item = ConsumeItem(&gItemRepository);
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "消费者" << std::this_thread::get_id()
<< "正在消费第" << item << "个产品" << std::endl;
}
}
else break;
}
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "消费者" << std::this_thread::get_id()
<< "退出" << std::endl;
}
} void InitItemRepository(ItemRepository *ir)
{
ir->write_position = ;
ir->read_position = ;
ir->item_counter = ;
} void test()
{
InitItemRepository(&gItemRepository);
std::thread producer1(ProducerTask);
std::thread producer2(ProducerTask);
std::thread producer3(ProducerTask);
std::thread producer4(ProducerTask);
std::thread consumer(ConsumerTask); producer1.join();
producer2.join();
producer3.join();
producer4.join();
consumer.join();
}

多消费者多生产者模式:

 struct ItemRepository
{
int item_buffer[kItemRepositorySize];
size_t read_position;
size_t write_position;
size_t produced_item_counter;
size_t consumed_item_counter;
std::mutex mtx;
std::mutex produced_item_counter_mtx;
std::mutex consumed_item_counter_mtx;
std::condition_variable repo_not_full;
std::condition_variable repo_not_empty;
} gItemRepository; typedef struct ItemRepository ItemRepository; void ProduceItem(ItemRepository *ir, int item)
{
std::unique_lock<std::mutex> lock(ir->mtx);
while (((ir->write_position + ) % kItemRepositorySize)
== ir->read_position)
{
// item buffer is full, just wait here.
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "缓冲区满,生产者等待中\n";
}
(ir->repo_not_full).wait(lock);
} (ir->item_buffer)[ir->write_position] = item;
(ir->write_position)++; if (ir->write_position == kItemRepositorySize)
ir->write_position = ; (ir->repo_not_empty).notify_all();
lock.unlock();
} int ConsumeItem(ItemRepository *ir)
{
int data;
std::unique_lock<std::mutex> lock(ir->mtx);
// item buffer is empty, just wait here.
while (ir->write_position == ir->read_position)
{
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "缓冲区空,消费者等待中\n";
}
(ir->repo_not_empty).wait(lock);
} data = (ir->item_buffer)[ir->read_position];
(ir->read_position)++; if (ir->read_position >= kItemRepositorySize)
ir->read_position = ; (ir->repo_not_full).notify_all();
lock.unlock(); return data;
} void ProducerTask()
{
bool ready_to_exit = false;
while ()
{
std::this_thread::sleep_for(std::chrono::milliseconds());
std::unique_lock<std::mutex> lock(gItemRepository.produced_item_counter_mtx);
if (gItemRepository.produced_item_counter < kItemsToProduce)
{
++(gItemRepository.produced_item_counter);
ProduceItem(&gItemRepository, gItemRepository.produced_item_counter);
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "生产者" << std::this_thread::get_id()
<< "正在生产第" << gItemRepository.produced_item_counter
<< "个产品" << std::endl;
}
}
else
{
ready_to_exit = true;
} lock.unlock();
if (ready_to_exit == true)
{
break;
}
}
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "生产者" << std::this_thread::get_id()
<< "退出" << std::endl;
}
} void ConsumerTask()
{
bool ready_to_exit = false;
while ()
{
std::this_thread::sleep_for(std::chrono::milliseconds());
std::unique_lock<std::mutex> lock(gItemRepository.consumed_item_counter_mtx);
if (gItemRepository.consumed_item_counter < kItemsToProduce)
{
int item = ConsumeItem(&gItemRepository);
++(gItemRepository.consumed_item_counter);
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "消费者" << std::this_thread::get_id()
<< "正在消费第" << item << "个产品" << std::endl;
}
}
else
{
ready_to_exit = true;
}
lock.unlock();
if (ready_to_exit == true)
{
break;
}
}
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << "消费者" << std::this_thread::get_id()
<< "退出" << std::endl;
}
} void InitItemRepository(ItemRepository *ir)
{
ir->write_position = ;
ir->read_position = ;
ir->produced_item_counter = ;
ir->consumed_item_counter = ;
} void test()
{
InitItemRepository(&gItemRepository);
std::thread producer1(ProducerTask);
std::thread producer2(ProducerTask);
std::thread producer3(ProducerTask);
std::thread producer4(ProducerTask); std::thread consumer1(ConsumerTask);
std::thread consumer2(ConsumerTask);
std::thread consumer3(ConsumerTask);
std::thread consumer4(ConsumerTask); producer1.join();
producer2.join();
producer3.join();
producer4.join(); consumer1.join();
consumer2.join();
consumer3.join();
consumer4.join();
}

注:

1、当缓存容量为n时,其实只能存放n-1个产品,主要原因是,当缓存满和空时,用取余无法区分

2、当单单模式变成多多模式时,只是针对单变多的某一方多添加一个读写锁

3、向标准缓冲区输出字符串时,由于是多线程的,所以需要使用读写锁来同步

完整实例下载:http://files.cnblogs.com/files/swarmbees/Producer_Consumer.zip

如果您觉得文章不错,不妨给个打赏,写作不易,感谢各位的支持。您的支持是我最大的动力,谢谢!!! 

 

很重要--转载声明

  1. 本站文章无特别说明,皆为原创,版权所有,转载时请用链接的方式,给出原文出处。同时写上原作者:朝十晚八 or Twowords
  2. 如要转载,请原文转载,如在转载时修改本文,请事先告知,谢绝在转载时通过修改本文达到有利于转载者的目的。

C++11 实现生产者消费者模式的更多相关文章

  1. python 并发编程 锁 / 信号量 / 事件 / 队列(进程间通信(IPC)) /生产者消费者模式

    (1)锁:进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 虽然使用加锁的形式实现了 ...

  2. 基于Java 生产者消费者模式(详细分析)

    Java 生产者消费者模式详细分析 本文目录:1.等待.唤醒机制的原理2.Lock和Condition3.单生产者单消费者模式4.使用Lock和Condition实现单生产单消费模式5.多生产多消费模 ...

  3. 2.5多线程(Java学习笔记)生产者消费者模式

    一.什么是生产者消费者模式 生产者生产数据存放在缓冲区,消费者从缓冲区拿出数据处理. 可能大家会问这样有何好处? 1.解耦 由于有了缓冲区,生产者和消费者之间不直接依赖,耦合度降低,便于程序拓展和维护 ...

  4. wait、notify应用场景(生产者-消费者模式)

    Java实现生产者消费者的方式有:wait && notify.BlockingQueue.Lock && Condition等 wait.notify注意事项:(1) ...

  5. 第三节: List类型的介绍、生产者消费者模式、发布订阅模式

    一. List类型基础 1.介绍 它是一个双向链表,支持左进.左出.右进.右出,所以它即可以充当队列使用,也可以充当栈使用. (1). 队列:先进先出, 可以利用List左进右出,或者右进左出(Lis ...

  6. java多线程 生产者消费者模式

    package de.bvb; /** * 生产者消费者模式 * 通过 wait() 和 notify() 通信方法实现 * */ public class Test1 { public static ...

  7. LabVIEW之生产者/消费者模式--队列操作 彭会锋

    LabVIEW之生产者/消费者模式--队列操作 彭会锋 本文章主要是对学习LabVIEW之生产者/消费者模式的学习笔记,其中涉及到同步控制技术-队列.事件.状态机.生产者-消费者模式,这几种技术在在本 ...

  8. 转:Task任务调度实现生产者消费者模式 (个人理解后文)

    纯属个人愚见.欢迎加入反驳(PiDou). 1.前文大致就是,利用Queue配置的一个TaskFactory任务调度器.实现生产者消费者模式的例子..首先我就试了 第一种 FIFO(先进先出)的配置. ...

  9. Lucene.net站内搜索—4、搜索引擎第一版技术储备(简单介绍Log4Net、生产者消费者模式)

    目录 Lucene.net站内搜索—1.SEO优化 Lucene.net站内搜索—2.Lucene.Net简介和分词Lucene.net站内搜索—3.最简单搜索引擎代码Lucene.net站内搜索—4 ...

随机推荐

  1. 在Eclipse中使用git把项目导入到git中--转载

    [转载出处注明:http://www.zhangxiaofu.cn/java/commonTools/2015/0607/764.html] 一.原有项目:  项目名为TestGit 二.在osc@g ...

  2. git clean 删除忽略文件 和 未被跟踪文件及文件夹

    git clean 删除忽略文件 和 未被跟踪文件及文件夹 概念 首先我们需要认清 忽略的文件 和 未被跟踪的文件 忽略的文件:.gitignore 中忽略的文件 未被跟踪的文件:没有被忽略,但是还没 ...

  3. Shell脚本学习 - 函数,输入输出重定向,文件

    函数 函数定义 [ function ] funname [()] { action; [return int;] } 定义时可以是function fun(),也可以直接fun(),不带参数 返回值 ...

  4. 对象关系映射 ORM

    1.1 作用 MTV框架中包括一个重要的部分,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因 ...

  5. sql server 2012 减少日志

    USE [master] GO ALTER DATABASE 数据库名 SET RECOVERY SIMPLE WITH NO_WAIT GO ALTER DATABASE 数据库名 SET RECO ...

  6. DataTable的Merge\COPY\AcceptChange使用说明

    在C#内使用DataTable的Merge().Copy().AcceptChange().Clone()方法的用途如下: 1.Merge()可将两个不同的表结构的表进行合并,合并后新表的列为之前两表 ...

  7. 用JS来判断版本号比如v21.2.2.2和v21.2.2.2.15

    当判断两个版本号的时候,不能单纯的去点然后相互比较,版本比较可能比较特殊,但是分析起来又挺简单的,既然不能直接去点比较,那就拆分成数组,一组一组对应的去比,为了能正常的进行比较 如果上一个版本长度小于 ...

  8. /usr/lib/python2.7/site-packages/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.22) or chardet (2.2.1) doesn't match a supported version! RequestsDependencyWarning)

    [root@iZwz9bhan5nqzh979qokrkZ ~]# ansible all -m ping /usr/lib/python2.7/site-packages/requests/__in ...

  9. 用Java写hello world

    public class HelloWorld{ public static void main(String[] args){ System.out.println("hello worl ...

  10. js的一些function

    /** * * 根据秒数返回 一个日期范围 * timerFilter(10) */ function timerFilter(n) { let days = 31; // 一月多少天 const o ...