当前位置: 首页 > news >正文

【Linux系统编程】用互斥量和信号量加锁STL容器,避免并发问题

目录

引言

容器模型

容器代码


个人主页:东洛的克莱斯韦克-CSDN博客

引言

STL容器并没有保证线程安全,而大多数应用场景下,为了追求效率,多线程是必不可少的。而底层容器难免会有并发问题。从设计上来说要么在上层代码做加锁处理,要么封装出能保证线程安全容器。

本文给出的方案是用信号量和互斥量封装vector容器——用两个信号量和两个互斥量封装出环形队列。

容器模型

给容器设计两个接口,push()用来向容器填充数据,pop用来向容器取数据。调用push接口的称为生产者,调用pop接口的称为消费者。

vector容器用下标回绕的方式,在逻辑上是一个环形。线程先去申请信号量资源,申请到了信号量资源的线程再去竞争互斥量,谁能锁住互斥量,谁就去容器里操作。

有了信号量和互斥量的存在,在任意时刻,有且只能有0或1个生产者,0或1个消费者线程在容器里操作。那么push接口和pop接口就是原子性的操作。

容器代码

#pragma once // 防止头文件被重复包含
//保证线程安全的环形队列容器
#include <vector>
#include <semaphore.h>
#include <pthread.h>#define C_MAX 300 //容器的容量template <class T>
class annular
{public:annular(int max_c = C_MAX): max_capacity(max_c), min_capacity(0), _c_subscript(0), _p_subscript(0){_v.reserve(max_c);pthread_mutex_init(&_c_lock, nullptr);pthread_mutex_init(&_p_lock, nullptr);sem_init(&_c_sem, 0, 0);sem_init(&_p_sem, 0, max_c);}~annular(){pthread_mutex_destroy(&_c_lock);pthread_mutex_destroy(&_p_lock);sem_destroy(&_c_sem);sem_destroy(&_p_sem);}void push(const T &data){sem_wait(&_p_sem);            // 信号量的p操作pthread_mutex_lock(&_p_lock); // 加锁_v[_p_subscript] = data;_p_subscript++;_p_subscript %= max_capacity;sem_post(&_c_sem);              // 信号量的v操作pthread_mutex_unlock(&_p_lock); // 解锁}void pop(T &data){sem_wait(&_c_sem);            // 信号量的p操作pthread_mutex_lock(&_c_lock); // 加锁data = _v[_c_subscript];_c_subscript++;_c_subscript %= max_capacity;sem_post(&_p_sem);              // 信号量的v操作pthread_mutex_unlock(&_c_lock); // 解锁}private:pthread_mutex_t _c_lock; // 消费者互斥量pthread_mutex_t _p_lock; // 生产者互斥量sem_t _c_sem;            // 消费者信号量sem_t _p_sem;            // 生产者信号量int _c_subscript;        // 消费者下标int _p_subscript;        // 生产者下标std::vector<T> _v;int max_capacity; // 容器最大容量int min_capacity; // 容器最小容量
};

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【鸿蒙OH-v5.0源码分析之 Linux Kernel 部分】005 - Kernel 入口 C 函数 start_kernel() 源码分析
  • 在linux下,找到指定命令对应的路径信息
  • MCN跨国企业如何从0到1搭建ITSM运维体系
  • MATLAB、FPGA、STM32中调用FFT计算频率、幅值及相位差
  • Spring 的循环依赖
  • MAC 地址简化概念(有线 MAC 地址、无线 MAC 地址、MAC 地址的随机化)
  • C++笔记---多态
  • 『功能项目』项目优化 - 框架加载资源【41】
  • 【计算机网络】HTTP相关问题与解答
  • ARM/Linux嵌入式面经(三五):诺瓦星云提前批
  • JavaScript高级——循环遍历加监听
  • 我的标志:奇特的头像
  • Error: ENOENT: no such file or directory, uv_cwd
  • jeesite支持db2数据库初始化sql
  • Ubuntu下安装最新版本Apache2文件服务器
  • [LeetCode] Wiggle Sort
  • 【108天】Java——《Head First Java》笔记(第1-4章)
  • Computed property XXX was assigned to but it has no setter
  • css属性的继承、初识值、计算值、当前值、应用值
  • js中forEach回调同异步问题
  • Python连接Oracle
  • rc-form之最单纯情况
  • React+TypeScript入门
  • Shell编程
  • 半理解系列--Promise的进化史
  • 计算机常识 - 收藏集 - 掘金
  • 简单数学运算程序(不定期更新)
  • 开源SQL-on-Hadoop系统一览
  • 深度学习在携程攻略社区的应用
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​Benvista PhotoZoom Pro 9.0.4新功能介绍
  • ​LeetCode解法汇总1410. HTML 实体解析器
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • ​软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】​
  • #includecmath
  • #微信小程序:微信小程序常见的配置传值
  • (19)夹钳(用于送货)
  • (arch)linux 转换文件编码格式
  • (cljs/run-at (JSVM. :browser) 搭建刚好可用的开发环境!)
  • (floyd+补集) poj 3275
  • (Java实习生)每日10道面试题打卡——JavaWeb篇
  • (多级缓存)缓存同步
  • (分布式缓存)Redis哨兵
  • (离散数学)逻辑连接词
  • (入门自用)--C++--抽象类--多态原理--虚表--1020
  • (一)Docker基本介绍
  • (转)Java socket中关闭IO流后,发生什么事?(以关闭输出流为例) .
  • (转载)虚函数剖析
  • .NET/ASP.NETMVC 深入剖析 Model元数据、HtmlHelper、自定义模板、模板的装饰者模式(二)...
  • .NET命名规范和开发约定
  • .Net转Java自学之路—基础巩固篇十三(集合)
  • @拔赤:Web前端开发十日谈
  • [12] 使用 CUDA 加速排序算法
  • [145] 二叉树的后序遍历 js
  • [C#学习笔记]注释