博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++ 实现多线程:生产者消费者模型
阅读量:4113 次
发布时间:2019-05-25

本文共 3787 字,大约阅读时间需要 12 分钟。

仓库用于存储生产好的产品,用循环数组来实现

  1. 生产者:多个生产者之间互斥,当仓库满时等待,否则将生产好的产品放入仓库
  2. 消费者:多个消费者之间互斥,当仓库空时等待,否则从仓库拿出一个产品进行消耗
#include 
#include
#include
#ifdef _MSC_VER#include
// windows#else#include
// linux#endif// 跨平台的延时函数:毫秒void mySleep(int milliseconds) {
#ifdef _MSC_VER Sleep(milliseconds);#else sleep(milliseconds);#endif}const int kProduceItems = 20; // 计划生产的产品个数const int kRepositorySize = 5; // 仓库大小// 仓库类template
class Repository { public: T items_buff[kRepositorySize]; // 数组实现环形队列 std::mutex mtx; // 生产者消费者互斥量 std::mutex produce_mutex; // 生产计数互斥量 std::mutex consume_mutex; // 消费计数互斥量 std::condition_variable repo_not_full; // 仓库不满条件变量 std::condition_variable repo_not_empty; // 仓库不空条件变量 size_t produce_item_count; // 生产数量计数 size_t consume_item_count; // 消费数量计数 size_t produce_position; // 下一个生产的位置 size_t consume_position; // 下一个消费的位置 Repository() { produce_item_count = 0; consume_item_count = 0; produce_position = 0; consume_position = 0; };};// 工厂类template
class Factory { private: Repository
repo; // 将生产好的产品放入仓库 void ProduceItem(Repository
&repo, T item) { std::unique_lock
lock(repo.mtx); // +1 后判断,因为在初始时,两者位于同一位置(因此仓库中最大存在 kRepositorySize-1 个产品) while ((repo.produce_position + 1) % kRepositorySize == repo.consume_position) { std::cout << "Repository is full, waiting..." << std::endl; repo.repo_not_full.wait(lock); // 阻塞时释放锁,被唤醒时获得锁 } repo.items_buff[repo.produce_position++] = item; if (repo.produce_position == kRepositorySize) repo.produce_position = 0; repo.repo_not_empty.notify_all(); // 唤醒所有因空阻塞的进程 lock.unlock(); } // 从仓库中拿取一个产品 T ConsumeItem(Repository
&repo) { std::unique_lock
lock(repo.mtx); while (repo.consume_position == repo.produce_position) { std::cout << "Repository is empty, waiting ..." << std::endl; repo.repo_not_empty.wait(lock); // 阻塞时释放锁,被唤醒时获得锁 } T data = repo.items_buff[repo.consume_position++]; if (repo.consume_position == kRepositorySize) repo.consume_position = 0; repo.repo_not_full.notify_all(); // 唤醒所有因满阻塞的进程 lock.unlock(); return data; }public: void ProduceTask() { bool ready_to_exit = false; while (true) { std::unique_lock
lock(repo.produce_mutex); if (repo.produce_item_count < kProduceItems) { // 结束线程条件 repo.produce_item_count++; // 生产产品代码块 //---------------------------------------------------- mySleep(1000); // 模仿消费产品需要的时间,实际运用中不需要 T item = repo.produce_item_count; std::cout << "producer id: " << std::this_thread::get_id() << " is producing item:\t[" << item << "]" << std::endl; //---------------------------------------------------- ProduceItem(repo, item); } else { ready_to_exit = true; } lock.unlock(); if (ready_to_exit) break; } } void ConsumeTask() { bool ready_to_exit = false; while (true) { std::unique_lock
lock(repo.consume_mutex); if (repo.consume_item_count < kProduceItems) { // 结束线程条件 T item = ConsumeItem(repo); // 消费产品代码块 //---------------------------------------------------- mySleep(1000); // 模仿消费产品需要的时间,实际运用中不需要 std::cout << "consumer id: " << std::this_thread::get_id() << " is consuming item:\t[" << item << "]" << std::endl; //---------------------------------------------------- repo.consume_item_count++; } else { ready_to_exit = true; } lock.unlock(); if (ready_to_exit) break; } }};int main() { std::cout << "Main thread id :" << std::this_thread::get_id() << std::endl; class Factory
myfactory; std::thread producer1(&Factory
::ProduceTask, &myfactory); std::thread producer2(&Factory
::ProduceTask, &myfactory); std::thread consumer1(&Factory
::ConsumeTask, &myfactory); std::thread consumer2(&Factory
::ConsumeTask, &myfactory); std::thread consumer3(&Factory
::ConsumeTask, &myfactory); producer1.join(); producer2.join(); consumer1.join(); consumer2.join(); consumer3.join();}

在windows上测试的输出结果

[注意]打印信息会因为多线程被打乱

windows上的测试,输出会因为线程打乱

转载地址:http://eywpi.baihongyu.com/

你可能感兴趣的文章
Ubuntu Could not open lock file /var/lib/dpkg/lock - open (13:Permission denied)
查看>>
collect2: ld returned 1 exit status
查看>>
C#入门
查看>>
查找最大值最小值
查看>>
C#中ColorDialog需点两次确定才会退出的问题
查看>>
数据库
查看>>
nginx反代 499 502 bad gateway 和timeout
查看>>
linux虚拟机安装tar.gz版jdk步骤详解
查看>>
python猜拳游戏
查看>>
python实现100以内自然数之和,偶数之和
查看>>
python数字逆序输出及多个print输出在同一行
查看>>
ESP8266 WIFI数传 Pixhaw折腾笔记
查看>>
苏宁产品经理面经
查看>>
百度产品经理群面
查看>>
去哪儿一面+平安科技二面+hr面+贝贝一面+二面产品面经
查看>>
element ui 弹窗在IE11中关闭时闪现问题修复
查看>>
vue 遍历对象并动态绑定在下拉列表中
查看>>
Vue动态生成el-checkbox点击无法选中的解决方法
查看>>
python __future__
查看>>
MySQL Tricks1
查看>>