【Linux】多线程_7

文章目录

  • 九、多线程
    • 8. POSIX信号量
      • 根据信号量+环形队列的生产者消费者模型代码
      • 结果演示
  • 未完待续


九、多线程

8. POSIX信号量

POSIX信号量和SystemV信号量作用相同,都是用于同步操作,达到无冲突的访问共享资源目的。 但POSIX可以用于线程间同步。
创建多线程的信号量:
在这里插入图片描述
销毁多线程之间的信号量:
在这里插入图片描述
对信号量做P操作(申请资源):
在这里插入图片描述
对信号量做V操作(释放资源):
在这里插入图片描述

根据信号量+环形队列的生产者消费者模型代码

Makefile

cp_ring:Main.ccg++ -o $@ $^ -std=c++11 -lpthread
.PHONY:clean
clean:rm -f cp_ring

Thread.hpp

#ifndef __THREAD_HPP__
#define __THREAD_HPP__#include <iostream>
#include <string>
#include <unistd.h>
#include <functional>
#include <pthread.h>namespace ThreadModule
{template<typename T>using func_t = std::function<void(T&, const std::string& name)>;template<typename T>class Thread{public:void Excute(){_func(_data, _threadname);}public:Thread(func_t<T> func, T& data, const std::string &name="none-name"): _func(func), _data(data), _threadname(name), _stop(true){}static void *threadroutine(void *args){Thread<T> *self = static_cast<Thread<T> *>(args);self->Excute();return nullptr;}bool Start(){int n = pthread_create(&_tid, nullptr, threadroutine, this);if(!n){_stop = false;return true;}else{return false;}}void Detach(){if(!_stop){pthread_detach(_tid);}}void Join(){if(!_stop){pthread_join(_tid, nullptr);}}std::string name(){return _threadname;}void Stop(){_stop = true;}~Thread() {}private:pthread_t _tid;std::string _threadname;T& _data;func_t<T> _func;bool _stop;};
}#endif

RingQueue.hpp

#pragma once#include <iostream>
#include <string>
#include <vector>
#include <semaphore.h>// 环形队列类模板
template<class T>
class RingQueue
{
private:// 申请资源void P(sem_t& sem){sem_wait(&sem);}// 释放资源void V(sem_t& sem){sem_post(&sem);}// 加锁void Lock(pthread_mutex_t& mutex){pthread_mutex_lock(&mutex);}// 解锁void Unlock(pthread_mutex_t& mutex){pthread_mutex_unlock(&mutex);}
public:RingQueue(int cap):_cap(cap),_ring_queue(cap),_prodeucer_step(0),_consumer_step(0){sem_init(&_room_sem, 0, _cap);sem_init(&_data_sem, 0, 0);pthread_mutex_init(&_prodeucter_mutex, nullptr);pthread_mutex_init(&_consumer_mutex, nullptr);}// 生产者的入队列函数void Enqueue(const T& in){// 申请空间资源P(_room_sem);// 加锁Lock(_prodeucter_mutex);// 入队列_ring_queue[_prodeucer_step++] = in;// 环形,绕一圈_prodeucer_step %= _cap;// 解锁Unlock(_prodeucter_mutex);// 释放数据资源V(_data_sem);}// 消费者的出队列函数void Pop(T* out){// 申请数据资源P(_data_sem);// 加锁Lock(_consumer_mutex);// 出队列*out = _ring_queue[_consumer_step++];_consumer_step %= _cap;// 解锁Unlock(_consumer_mutex);// 释放空间资源V(_room_sem);}~RingQueue(){sem_destroy(&_room_sem);sem_destroy(&_data_sem);pthread_mutex_destroy(&_prodeucter_mutex);pthread_mutex_destroy(&_consumer_mutex);}
private:// 数组模拟环形队列std::vector<T> _ring_queue;// 容量int _cap;// 生产者和消费者的位置指针int _prodeucer_step;int _consumer_step;// 信号量sem_t _room_sem;sem_t _data_sem;// 互斥锁pthread_mutex_t _prodeucter_mutex;pthread_mutex_t _consumer_mutex;
};

Task.hpp

#pragma once#include <iostream>
#include <functional>using Task = std::function<void()>;void Download()
{std::cout << "Downloading..." << std::endl;
}

Main.cc

#include "RingQueue.hpp"
#include "Thread.hpp"
#include "Task.hpp"
#include <string>
#include <vector>
#include <unistd.h>using namespace ThreadModule;
// 创建类型别名
using ringqueue_t = RingQueue<Task>;// 消费者线程
void Consumer(ringqueue_t& rq, const std::string& name)
{while (true){// 获取任务Task t;rq.Pop(&t);std::cout << "Consumer " << name << " : ";// 执行任务t();}
}// 生产者线程
void Productor(ringqueue_t& rq, const std::string& name)
{while (true){// 发布任务rq.Enqueue(Download);std::cout << "Productor " << name << " : " << "Download task" << std::endl;sleep(1);}
}// 启动线程
void InitComm(std::vector<Thread<ringqueue_t>>* threads, int num, ringqueue_t& rq, func_t<ringqueue_t> func)
{for (int i = 0; i < num; i++){// 创建一批线程std::string name = "thread-" + std::to_string(i + 1);threads->emplace_back(func, rq, name);}
}// 创建消费者线程
void InitConsumer(std::vector<Thread<ringqueue_t>>* threads, int num, ringqueue_t& rq)
{InitComm(threads, num, rq, Consumer);
}// 创建生产者线程
void InitProductor(std::vector<Thread<ringqueue_t>>* threads, int num, ringqueue_t& rq)
{InitComm(threads, num, rq, Productor);
}// 等待所有线程结束
void WaitAllThread(std::vector<Thread<ringqueue_t>>& threads)
{for (auto& thread : threads){thread.Join();}
}// 启动所有线程
void StartAll(std::vector<Thread<ringqueue_t>>& threads)
{for (auto& thread : threads){thread.Start();}
}int main()
{// 创建阻塞队列,容量为5ringqueue_t* rq = new ringqueue_t(10);// 创建线程std::vector<Thread<ringqueue_t>> threads;// 创建 1个消费者线程InitConsumer(&threads, 1, *rq);// 创建 1个生产者线程InitProductor(&threads, 1, *rq);// 启动所有线程StartAll(threads);// 等待所有线程结束WaitAllThread(threads);return 0;
}

结果演示

在这里插入图片描述
这里演示的是单生产者单消费者的模型,可以在主函数改成多生产者多消费者的模型。


未完待续

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

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

相关文章

什么ISP?什么是IAP?

做单片机开发的工程师经常会听到两个词&#xff1a;ISP和IAP&#xff0c;但新手往往对这两个概念不是很清楚&#xff0c;今天就来和大家聊聊什么是ISP&#xff0c;什么是IAP&#xff1f; 一、ISP ISP的全称是&#xff1a;In System Programming&#xff0c;即在系统编程&…

如何申请抖音本地生活服务商?3种方式优劣势分析!

随着多家互联网大厂在本地生活板块的布局力度不断加大&#xff0c;以抖音为代表的头部互联网平台的本地生活服务商成为了创业赛道中的大热门&#xff0c;与抖音本地生活服务商怎么申请等相关的帖子&#xff0c;更是多次登顶创业者社群的话题榜单。 就目前的市场情况来看&#x…

Go语言--广播式并发聊天服务器

实现功能 每个客户端上线&#xff0c;服务端可以向其他客户端广播上线信息&#xff1b;发送的消息可以广播给其他在线的客户支持改名支持客户端主动退出支持通过who查找当前在线的用户超时退出 流程 变量 用户结构体 保存用户的管道&#xff0c;用户名以及网络地址信息 typ…

ARM功耗管理之功耗数据与功耗收益评估

安全之安全(security)博客目录导读 思考&#xff1a;功耗数据如何测试&#xff1f;功耗曲线&#xff1f;功耗收益评估&#xff1f; UPF的全称是Unified Power Format&#xff0c;其作用是把功耗设计意图&#xff08;power intent&#xff09;传递给EDA工具&#xff0c; 从而帮…

Codeforces Round 958 (Div. 2)补题

文章目录 A题 (拆分多集)B题(获得多数票)C题&#xff08;固定 OR 的递增序列&#xff09; A题 (拆分多集) 本题在赛时卡的时间比较久&#xff0c;把这题想复杂了&#xff0c;导致WA了两次。后来看明白之后就是将n每次转换成k-1个1&#xff0c;到最后分不出来k-1个1直接一次就能…

Hive的基本操作(查询)

1、基础查询 基本语法 select 字段列表|表达式|子查询 from 表(子查询|视图|临时表|普通表) where [not] 条件A and|or 条件B --先&#xff1a;面向原始行进行筛选 group by 字段A[,字段B,...] > 分组【去重处理】 having 聚合条件(非原始字段条件) --再&#x…

JMeter案例分享:通过数据验证的错误,说说CSV数据文件设置中的线程共享模式

前言 用过JMeter参数化的小伙伴&#xff0c;想必对CSV Data Set Config非常熟悉。大家平时更关注变量名称&#xff0c;是否忽略首行等参数&#xff0c;其余的一般都使用默认值。然而我最近遇到一个未按照我的预想读取数据的案例&#xff0c;原因就出在最后一个参数“线程共享模…

深度学习中激活函数的演变与应用:一个综述

摘要 本文全面回顾了深度学习中激活函数的发展历程,从早期的Sigmoid和Tanh函数,到广泛应用的ReLU系列,再到近期提出的Swish、Mish和GeLU等新型激活函数。深入分析了各类激活函数的数学表达、特点优势、局限性以及在典型模型中的应用情况。通过系统的对比分析,本文探讨了激…

详解MySQL中的递归查询

MySQL中的递归查询主要通过WITH RECURSIVE语句来实现&#xff0c;这在处理具有层级关系或树形结构的数据时非常有用。下面将通过一个具体的例子来详细解释如何在MySQL中使用递归查询。 示例场景 假设我们有一个部门表&#xff08;departments&#xff09;&#xff0c;其中包含…

老板新招的牛人,竟然用1天搭建了一套完整的仓库管理系统!

仓储管理系统是什么&#xff1f; 仓储管理系统&#xff08;WMS&#xff09;是一个全面的软件解决方案&#xff0c;旨在帮助企业优化仓库管理流程、管理和控制日常仓库运营。通过数学模型和信息手段&#xff0c;对仓库管理的各个环节进行优化和调控&#xff0c;涵盖了从货物入库…

使用网关和Spring Security进行认证和授权

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

怎么录制视频?电脑录制,试试这3种方法

在数字化快速发展的时代&#xff0c;视频已经成为我们传递信息、分享生活、表达情感的重要载体。每一个人都希望自己能够掌握视频录制技巧&#xff0c;轻松驾驭影像的力量&#xff0c;创造出属于自己的视觉盛宴。 那么&#xff0c;怎么录制视频呢&#xff1f;首先选择一款好用…

《信息与电脑(理论版)》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答 问&#xff1a;《信息与电脑(理论版)》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的正规学术期刊。 问&#xff1a;《信息与电脑(理论版)》级别&#xff1f; 答&#xff1a;省级。主管单位&#xff1a;北京电子控股有限责任公司 主办…

实践致知第16享:设置Word中某一页横着的效果及操作

一、背景需求 小姑电话说&#xff1a;现在有个word文档,里面有个表格太长&#xff08;如下图所示&#xff09;&#xff0c;希望这一个设置成横的&#xff0c;其余页还是保持竖的&#xff01; 二、解决方案 1、将鼠标放置在该页的最前面闪烁&#xff0c;然后选择“页面”》“↘…

【Stable Diffusion】(基础篇三)—— 图生图基础

图生图基础 本系列笔记主要参考B站nenly同学的视频教程&#xff0c;传送门&#xff1a;B站第一套系统的AI绘画课&#xff01;零基础学会Stable Diffusion&#xff0c;这绝对是你看过的最容易上手的AI绘画教程 | SD WebUI 保姆级攻略_哔哩哔哩_bilibili 本文主要讲解如何使用S…

K8s集群初始化遇到的问题

kubectl describe pod coredns-545d6fc579-s9g5s -n kube-system 找到原因1&#xff1a;CoreDNS Pod 处于 Pending 状态的原因是集群中的节点都带有 node.kubernetes.io/not-ready 污点 journalctl -u kubelet -f 14:57:59.178592 3553 remote_image.go:114] "PullIma…

pear-admin-fast项目修改为集成PostgreSQL启动

全局搜索代码中的sysdate()&#xff0c;修改为now() 【前者是mysql特有的&#xff0c;后者是postgre特有的】修改application-dev.yml中的数据库url使用DBeaver把mysql中的数据库表导出csv&#xff0c;再从postgre中导入csv脚本转换后出现了bpchar(xx)类型&#xff0c;那么一定…

python数据可视化(6)——绘制散点图

课程学习来源&#xff1a;b站up&#xff1a;【蚂蚁学python】 【课程链接&#xff1a;【【数据可视化】Python数据图表可视化入门到实战】】 【课程资料链接&#xff1a;【链接】】 Python绘制散点图查看BMI与保险费的关系 散点图: 用两组数据构成多个坐标点&#xff0c;考察…

如何降低老年人患帕金森病的风险?

降低老年人患帕金森病风险的方法 避免接触有害物质&#xff1a;长期接触某些化学物质、农药或其他有害物质可能会增加患帕金森病的风险。应减少这些物质的暴露&#xff0c;例如在工作或生活中采取防护措施。 健康饮食&#xff1a;均衡饮食&#xff0c;多吃富含抗氧化剂的食物&a…

做了一个万能搜索框

最近给网页做了一个搜索框&#xff0c;现在搜索比以前更加方便了&#xff0c;下面简单介绍一下如何使用 我们进入网页版&#xff08;app.zyjj.cc&#xff09;点击右上角的搜索就可以看到这个新版的搜索框了 目前支持中文、拼音、首字母等多种搜索方式&#xff0c;大家可以随意…