多线程生产者消费者——分别使用条件变量、信号量实现

news2024/11/15 19:32:00

生产者消费者

概念

生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。这个阻塞队列就是用来给生产者和消费者解耦的。

321原则

  • 三种角色:生产者、消费者、仓库

  • 两种关系:生产者与生产者之间是互斥关系,消费者与消费者之间是互斥关系,生产者与消费者之间是同步与互斥关系。

  • 一个交易场所:仓库

优点

  • 解耦–生产者。消费者之间不直接通信,降低了耦合度。

  • 支持并发

  • 支持忙闲不均


条件变量实现

使用条件变量控制生产者消费者的极限状态:即产品满的时候,生产者进行等待;即产品空的时候,消费者进行等待

使用互斥锁对临界资源的访问进行保护,即保护产品队列

使用C++11线程支持库std::condition_variable(条件变量)std::mutex(互斥锁)完成多线程的访问控制。

class My_Queue {
private:
	std::condition_variable _cond;
	std::mutex _mtx;
	queue<int> _que;
	int _max;
public:
	My_Queue(int max = 5) :_max(max) {}
	bool IsFull() {
		return _que.size() == _max;
	}
	bool IsEmpty() {
		return _que.size() == 0;
	}
	int put(int val) {
		std::unique_lock<std::mutex> Lock(_mtx);
		while (IsFull()) {
			_cond.wait(Lock);
		}
		_que.push(val);
		_cond.notify_all();
		return val;
	}
	int out() {
		std::unique_lock<std::mutex> Lock(_mtx);
		while (IsEmpty()) {
			_cond.wait(Lock);
		}
		int res = _que.front();
		_que.pop();
		_cond.notify_all();
		return res;
	}
};

const int n = 5;
My_Queue que(n);

void Producter()
{
	srand((unsigned int)time(NULL));
	while (1) {
		//std::this_thread::sleep_for(std::chrono::milliseconds(2000));
		cout << "Producter:" << que.put(rand() % 100) << endl;
	}
}

void Consumer()
{
	srand((unsigned int)time(NULL));
	while (1) {
		//std::this_thread::sleep_for(std::chrono::milliseconds(1000));
		cout << "Consumer:" << que.out() << endl;
	}
}

int main()
{
	thread tha(Producter, 1);
	thread thb(Producter, 2);
	thread thc(Producter, 3);
	thread thd(Consumer, 1);
	thread the(Consumer, 2);

	tha.join();
	thb.join();
	thc.join();
	thd.join();
	the.join();
}

测试

由于多线程发生并行,导致同一时间中,多个生产者产生相同随机值


信号量实现

两个信号量实现等待状态,生产者信号量与消费者信号量

当生产者信号量wait阻塞,说明产品到达极限,无法生产

当消费者信号量wait阻塞,说明产品消耗完成,无法继续获取

使用互斥锁对临界资源访问进行控制

在linux下使用原生线程支持库中pthread_mutex、sem完成

由于服务器为单核,所以不做多线程测试,有意者可自行尝试

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <semaphore.h>

#define SIZE 6

int Warehouse[SIZE];

pthread_mutex_t mutex;
sem_t sem_pro;//生产者信号量
sem_t sem_con;//消费者信号量
int num = 0;

void* Producter(void* arg)
{
    while (1)
    {
        sem_wait(&sem_pro);
        pthread_mutex_lock(&mutex);
        Warehouse[num] = rand() % 100 + 1;
        printf("product Warehouse[%d] =  %d\n", num, Warehouse[num]);
        num++;
        sem_post(&sem_con);
        pthread_mutex_unlock(&mutex);
        sleep(1);
    }
}

void* Consumer(void* arg)
{
    while (1)
    {
        sem_wait(&sem_con);
        pthread_mutex_lock(&mutex);
        num--;
        printf("consum Warehouse[%d] =  %d\n", num, Warehouse[num]);
        sem_post(&sem_pro);
        pthread_mutex_unlock(&mutex);
        sleep(2);
    }
}

int main()
{
    pthread_mutex_init(&mutex, NULL);
    sem_init(&sem_pro, 0, 6);//生产者信号量值初始化为6 意为可容纳产品空间为6
    sem_init(&sem_con, 0, 0);

    pthread_t id[2];
    pthread_create(&id[0], NULL, Producter, NULL);
    pthread_create(&id[1], NULL, Consumer, NULL);

    pthread_join(id[0], NULL);
    pthread_join(id[1], NULL);

    exit(0);
}

测试

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/131532.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

超好用!win10安装Eiseg标注软件及使用(CPU版本)

写在前面的话 众所周知&#xff0c;标注分割掩膜的软件一般使用labelme&#xff0c;但是一个一个点太麻烦了&#xff0c;工作量太大&#xff0c;&#xff0c;之前&#xff0c;我的思路就是先标少量的数据然后训练个初始模型&#xff0c;再用初始模型对剩下的图像预测掩膜&…

【闲聊杂谈】深入理解Spring Security设计原理

1、什么是Spring Security 顾名思义&#xff0c;Security的意思是安全&#xff0c;本质上就是一个很纯粹的权限管理框架&#xff0c;提供认证和授权两大核心功能。在目前主流的Spring生态中的项目&#xff0c;说到安全框架&#xff0c;基本上SpringSecurity是首选。当然&#…

代码随想录算法训练营第四天|24. 两两交换链表中的节点 、19.删除链表的倒数第N个节点、160.链表相交、142.环形链表II

24. 两两交换链表中的节点 力扣题目链接(opens new window) 解析&#xff1a; 基础题&#xff0c;主要是要把握边界条件&#xff1a;由题可得&#xff0c;交换的节点两两一组&#xff0c;每交换完成一对&#xff0c;问题规模减2&#xff0c;也就是只剩一个或不剩节点时交换便结…

ArcGIS基础实验操作100例--实验28地形图配准

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 高级编辑篇--实验28 地形图配准 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;1&#x…

python中类的使用详解

目录 一.类的定义和使用方法 成员变量和成员方法 成员方法的定义语法和self关键字 小结 二.类和对象 小结 三.属性&#xff08;成员变量&#xff09;的赋值 构造方法&#xff1a;_ _init_ _() 小结 一.类的定义和使用方法 可以使用类去封装属性&#xff0c;并基于类创建…

一文弄懂Pytorch的DataLoader,Dataset,Sampler之间的关系

很多文章都是从DatasetDatasetDataset等对象自下网上进行介绍的&#xff0c;但是对于初学者而言&#xff0c;其实这并不好理解&#xff0c;因为有时候&#xff0c;会不自觉的陷入到一些细枝末节中去&#xff0c;而不能把握重点&#xff0c;所以本文将自上而下的对PytorchPytorc…

HCIP第四天

HCIP实验配置一&#xff0c;实验要求二&#xff0c;172.16.0.0/16地址的划分三&#xff0c;搭建拓扑图四&#xff0c;配置IP地址和环回地址五&#xff0c;宣告并配置缺省路由下放&#xff0c;使用NAT技术六&#xff0c;R5中心站点配置隧道和静态IP七&#xff0c;R6分支站点的配…

canvas在小程序里写小游戏

最近接了个小需求需要写个小游戏&#xff0c;由简单的帧动画加上碰撞相关的处理&#xff0c;组成。具体页面信息如下图 具体的游戏步骤&#xff0c;是通过长按按钮蓄力&#xff0c;松开时卡通人物跳起&#xff0c;卡通人物跳起碰撞到上面的元宝等元素的得分&#xff0c;这里我们…

笔试题之编写SQL分析门店销售情况

销售员、客户、产品 文章目录前言一、SQL题目二、解答方法&#xff08;一&#xff09;建表插入测试数据&#xff08;二&#xff09;第一题解答&#xff08;三&#xff09;第二题解答&#xff08;四&#xff09;第三题解答总结前言 分享本人遇到的笔试真题与解法&#xff0c;并…

MATLAB算法实战应用案例精讲-【人工智能】语义分割(附实战应用案例及代码)

前言 语义分割是一种典型的计算机视觉问题,其涉及将一些原始数据(例如,平面图像)作为输入并将它们转换为具有突出显示的感兴趣区域的掩模。许多人使用术语全像素语义分割(full-pixel semantic segmentation),其中图像中的每个像素根据其所属的感兴趣对象被分配类别ID。…

[ XSS-labs通关宝典 ] xss-labs 通关宝典之 less1 - less5

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

前端常见问题汇总(十)

一、HTTP1.0和HTTP2.0的区别 http1.0&#xff1a;每次请求都需要重新建立tcp连接&#xff0c;请求完后立即断开与服务器连接&#xff0c;这很大程度造成了性能上的缺陷&#xff0c;http1.0被抱怨最多的就是连接无法复用。 http1.1&#xff1a;引入了长连接&#xff08;keep-al…

麒麟系统虚拟机安装教程

作者&#xff1a;朱金灿 来源&#xff1a;clever101的专栏 为什么大多数人学不会人工智能编程&#xff1f;>>> 1.首先得安装VM Ware软件。 2.打开VM Ware&#xff0c;点击“文件”->“新建虚拟机”。 3.进入新建虚拟机向导&#xff0c;点击下一步。如下图&…

API管理神器:Apifox

前言 代码未动&#xff0c;文档先行 其实大家都知道 API 文档先行的重要性&#xff0c;但是在实践过程中往往会遇到很多困难。 程序员最讨厌的两件事&#xff1a;1. 写文档&#xff0c;2. 别人不写文档。大多数开发人员不愿意写 API 文档的原因是写文档短期收益远低于付出的…

2023—静待“雨中的海棠”发芽

2023—静待“雨中的海棠”发芽认真负责、全身心的投入工作减少抱怨勤思考、多总结—>高效工作保持7*24小时在线全身心BKGWY坚持不懈多运动骑车车、练哑铃、慢跑多看书看自己喜欢的书环青海湖准备环青海湖的攻略身体上的准备内心信念的支撑最后就静待“雨中的海棠”发芽吧&am…

kali - 扫描

数据来源 Whatweb WhateWhatweb是一个基于Ruby语言的开源网站指纹识别软件&#xff0c;正如它的名字一样,&#xff0c;whate能够识别各种关于网站的详细信息&#xff0c;包括&#xff1a;CMS类型、博客平台、中间件、web框架模块、网站服务器、脚本类型、 Javascript库、lP、 …

Apollo 配置中心

Apollo 配置中心目录概述需求&#xff1a;设计思路实现思路分析1.Apollo 配置中心2.Client端配置中心3.爬虫调度器5.Server端配置中心参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardne…

(免费分享)基于jsp,ssm甜点网站

开发工具&#xff1a;eclipse&#xff0c;jdk1.8 数据库&#xff1a;mysql5.7&#xff0c;Tomcat8.0 package com.softeem.controller;import java.util.HashMap; import java.util.Map;import javax.annotation.Resource;import org.springframework.stereotype.Controller; …

labelImag安装及使用教程

在做目标检测任务时&#xff0c;需要进行标注&#xff0c;选择了LabelImg作为标注工具&#xff0c;下面是安装及使用过程。 我们使用Anconda的虚拟环境进行安装&#xff0c;激活环境后&#xff0c;执行&#xff1a; pip install labelimg -i https://pypi.tuna.tsinghua.edu.c…

WebSocket 协议详述( java在线聊天室_上篇)

文章目录1、 WebSocket 协议1.1、 何为WebSocket&#xff1f;1.2、 websocket 和 http&#xff08;应用层的俩个协议&#xff09;1.3、 websocket协议的具体过程1.4、websocket好处2、 WebSocket实现2.1、 客户端实现2.1.1、 websocket对象2.1.2、 websocket事件2.1.3、 websoc…