C++多线程 生产者 消费者示例
之前写过一篇关于多线程的https://blog.csdn.net/qq_21049875/article/details/79589126。
为了复习一下C++多线程的使用,以及程序的编写,于是写了一个生产者与消费者。
在编写的过程中了解了条件变量(std::condition_variable)的使用,可以让线程挂起和叫醒线程,以及之前编写一些示例代码的时候一直用的是std::locak_guard,而不是std::unique_lock,两者都是RAII(获取资源立即初始化 ),而后者比较灵活,提供了lock(),unlock(),try_lock(),接口。
std::unique_lock的源代码中大概是封装了mutex的一些接口,下面从其他博客复制了mutex的接口信息。)
lock(),调用线程将锁住该互斥量。线程调用该函数会发生下面 3 种情况:
(1). 如果该互斥量当前没有被锁住,则调用线程将该互斥量锁住,直到调用 unlock之前,该线程一直拥有该锁。
(2). 如果当前互斥量被其他线程锁住,则当前的调用线程被阻塞住。
(3). 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。
unlock(), 解锁,释放对互斥量的所有权。
try_lock(),尝试锁住互斥量,如果互斥量被其他线程占有,则当前线程也不会被阻塞。线程调用该函数也会出现下面 3 种情况:
(1). 如果当前互斥量没有被其他线程占有,则该线程锁住互斥量,直到该线程调用 unlock 释放互斥量。
(2). 如果当前互斥量被其他线程锁住,则当前调用线程返回 false,而并不会被阻塞掉。
(3). 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。
下面代码编写中碰到的问题,在productItem与consumeItem的时候,都有对互斥量mtx上锁的过程,在productItem的代码里有一个Sleep,是为了让消费者能够消费到商品,要不然就由于计算机速度太快,直接生产满了,就碰到while(item…)直接出发is_full造成后面运行后生产者进入死锁状态。
当然,你可以编写一个对is_full这个条件变量相应的函数,比如item满了就扔掉一个,去解锁is_full然后唤醒product线程,这样就不需要Sleep函数啦~
还有,可以用std::this_thread::yield()来实现把执行的线程时间片让给其他线程使用,就比如item满了之后让其他线程运行,或者是std::this_thread::sleep_for() 让线程睡一下,更或者直接sleep……hah….
代码:
#include<iostream>
#include<vector>
#include<thread>
#include<queue>
#include<mutex>
#include<Windows.h>
class demo {
private:
condition_variable is_full;
condition_variable is_empty;
mutex mtx;
vector<std::thread> tpool;
private:
queue<int> item_buff;
const int buffsize;
static int item_id;
int c_no, p_no;
private:
void producItem() {
while (true) {
std::unique_lock<mutex> lck(mtx);
while (item_buff.size() == buffsize) {
is_full.wait(lck);
}
item_id = item_id++ %buffsize;
item_buff.push(item_id);
cout << "product item id: " << item_id << endl;
lck.unlock();
is_empty.notify_all();
Sleep(10);
}
}
void consumeItem() {
while (true) {
std::unique_lock<mutex> lck(mtx);
while (item_buff.empty()) {
cout << "wait product" << endl;
is_full.notify_one();
is_empty.wait(lck);
}
cout << "customer id : " << this_thread::get_id() << endl;
cout << "consume Item id: " << item_buff.front() << endl;
item_buff.pop();
lck.unlock();
}
}
public:
demo(int size = 10, int pno = 1, int cno = 5) :buffsize(size), p_no(pno), c_no(cno) {};
void run() {
productTask();
customerTask();
for (auto &i : tpool) {
i.join();
}
}
void productTask() {
for (int i = 0; i < p_no; i++) {
tpool.emplace_back(thread(&demo::producItem, this));
}
}
void customerTask() {
for (int i = 0; i < c_no; i++) {
tpool.emplace_back(thread(&demo::consumeItem, this));
}
}
};
int demo::item_id = 0;
int main()
{
demo t;
t.run();
return 0;
}
C++多线程 生产者 消费者示例的更多相关文章
- java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-【费元星Q9715234】
java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-[费元星Q9715234] 说明如下,不懂的问题直接我[费元星Q9715234] 1.反射的意义在于不将xml tag ...
- Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例
Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例 本文由 TonySpark 翻译自 Javarevisited.转载请参见文章末尾的要求. Java.util.concurr ...
- python自动化--语言基础线程、生产者消费者示例
进程与线程的区别:进程不共享空间,线程共享地址空间 线程共享空间优缺点:优点:多线程给用户的体验好些,打开时占用的内存比进程少缺点:共享地址空间会相互干扰,甚至有影响 import threading ...
- Python多线程-生产者消费者模型
用多线程和队列来实现生产者消费者模型 # -*- coding:utf-8 -*- __author__ = "MuT6 Sch01aR" import threading imp ...
- Java实现多线程生产者消费者模式的两种方法
生产者消费者模式:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据.生产者生产一个,消费者消费一个,不断循环. 第一种实现方法,用BlockingQueue阻塞队 ...
- 多线程-生产者消费者(synchronized同步)
正解博客:https://blog.csdn.net/u011863767/article/details/59731447 永远在循环(loop)里调用 wait 和 notify,不是在 If 语 ...
- java多线程 生产者消费者模式
package de.bvb; /** * 生产者消费者模式 * 通过 wait() 和 notify() 通信方法实现 * */ public class Test1 { public static ...
- [多线程] 生产者消费者模型的BOOST实现
说明 如果 使用过程中有BUG 一定要告诉我:在下面留言或者给我邮件(sawpara at 126 dot com) 使用boost::thread库来实现生产者消费者模型中的缓冲区! 仓库内最多可以 ...
- Java实现多线程生产者消费者模型及优化方案
生产者-消费者模型是进程间通信的重要内容之一.其原理十分简单,但自己用语言实现往往会出现很多的问题,下面我们用一系列代码来展现在编码中容易出现的问题以及最优解决方案. /* 单生产者.单消费者生产烤鸭 ...
随机推荐
- bootstrap插件的一些常用属性介绍
1.下拉菜单 <div class="dropdown"> <button class="btn btn-default dropdown-toggle ...
- Xenu Link Sleuth 简单好用的链接测试工具 使用说明
XenuLink Sleuth 名词介绍 “Xenu链接检测侦探”是被广泛使用的死链接检测工具.可以检测到网页中的普通链接.图片.框架.插件.背景.样式表.脚本和java程序中的链接. 那么神马时候出 ...
- Linux Tomcat 7.0 管理员登录时"401 Unauthorized" 问题解决方法
http://blog.csdn.net/u010359532/article/details/36055291 tomcat 7.0没有默认值,需要在conf的tomcat-users.xml中设置 ...
- 小学生作业V2.0
211606320刘佳&211506332熊哲琛 一.预估与实际 PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟) Plann ...
- Word编写代码时输出半角引号
工具--自动更正选项--键入时自动套用格式,去掉直引号替换为弯引号.
- Redis搭建(七):Redis的Cluster集群动态增删节点
一.引言 上一篇文章我们一步一步的教大家搭建了Redis的Cluster集群环境,形成了3个主节点和3个从节点的Cluster的环境.当然,大家可以使用 Cluster info 命令查看Cluste ...
- Linux学习---linux系统下安装配置Jenkins
1.首先准备java环境,安装JDK 2.下载jenkins至Linux服务器 下载地址:https://wiki.jenkins-ci.org/display/JENKINS/Installing+ ...
- 95. Unique Binary Search Trees II (Tree; DFS)
Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. For e ...
- 把二叉搜索树转化成更大的树 · Convert BST to Greater Tree
[抄题]: 给定二叉搜索树(BST),将其转换为更大的树,使原始BST上每个节点的值都更改为在原始树中大于等于该节点值的节点值之和(包括该节点). Given a binary search Tree ...
- Ubuntu下U盘只读文件系统,图标上锁,提示无法修改
资料来源于网络,自己总结 问题 Ubuntu下有时候插入U盘,发现不能修改其中的内容.例如不能新建文件和文件夹,不能向U盘中复制文件等,系统提示:只读文件系统. 原因大概是U盘的文件系统信息出错(保存 ...