C++实现多线程安全的生产者消费者字节缓冲区

文章目录

    • 介绍
    • 实现细节
      • **BytesBuffer 类**
      • **生产者和消费者**
    • 性能优化
    • 总结

介绍

本文介绍如何使用C++实现一个多线程安全的简单字节缓冲区,并进行性能测试。

实现细节

BytesBuffer 类

BytesBuffer 类通过使用条件变量和双缓冲区机制,实现了生产者和消费者之间的高效数据传输。该类的主要功能包括数据追加(append)和数据检索(retrieve)。下面是具体实现:

#ifndef BYTE_BUFFER_BUFFER_H_
#define BYTE_BUFFER_BUFFER_H_#include <algorithm>
#include <atomic>
#include <condition_variable>
#include <cstring>
#include <mutex>
#include <vector>class BytesBuffer {public:static const size_t kInitialSize = 1024;explicit BytesBuffer(size_t capacity = kInitialSize): capacity_(capacity),buffer1_(capacity),buffer2_(capacity),current_buffer_(&buffer1_),temp_buffer_(&buffer2_),stop_(false) {}void append(const char* data, size_t length) {std::unique_lock<std::mutex> lock(mutex_);for (size_t i = 0; i < length; ++i) {while (!stop_ && current_buffer_->size() >= capacity_) {not_full_.wait(lock);  // 等待足够空间写入}if (stop_) return;current_buffer_->push_back(data[i]);not_empty_.notify_one();}}size_t retrieve(char* target, size_t maxLength) {std::unique_lock<std::mutex> lock(mutex_);while (!stop_ && current_buffer_->empty()) {not_empty_.wait(lock);  // 等待有数据可读}if (stop_) return 0;std::swap(current_buffer_, temp_buffer_);lock.unlock();size_t bytes_to_read = std::min(maxLength, temp_buffer_->size());std::memcpy(target, temp_buffer_->data(), bytes_to_read);temp_buffer_->clear();lock.lock();not_full_.notify_one();return bytes_to_read;}void stop() {std::unique_lock<std::mutex> lock(mutex_);stop_ = true;not_empty_.notify_all();not_full_.notify_all();}bool isStopped() const {return stop_.load();}private:size_t capacity_;std::vector<char> buffer1_;std::vector<char> buffer2_;std::vector<char>* current_buffer_;std::vector<char>* temp_buffer_;std::mutex mutex_;std::condition_variable not_empty_;std::condition_variable not_full_;std::atomic<bool> stop_;BytesBuffer(const BytesBuffer&) = delete;BytesBuffer& operator=(const BytesBuffer&) = delete;
};#endif  // BYTE_BUFFER_BUFFER_H_

生产者和消费者

生产者和消费者函数分别向缓冲区追加数据和从缓冲区检索数据。

#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
#include "bytes_buffer.hpp"void Producer(BytesBuffer* buffer, std::atomic<bool>& running) {const char data[] = "测试数据";while (running.load()) {buffer->append(data, std::strlen(data));}
}void Consumer(BytesBuffer* buffer, std::atomic<bool>& running) {char output[1024];while (running.load()) {buffer->retrieve(output, sizeof(output));}
}int main() {BytesBuffer buffer(1024);std::atomic<bool> running(true);std::thread producer_thread(Producer, &buffer, std::ref(running));std::thread consumer_thread(Consumer, &buffer, std::ref(running));// 运行测试5秒钟std::this_thread::sleep_for(std::chrono::seconds(5));// 信号线程停止并加入它们running.store(false);buffer.stop();producer_thread.join();consumer_thread.join();std::cout << "测试完成" << std::endl;return 0;
}

性能优化

  1. 减少锁的持有时间:在 retrieve 方法中,交换当前缓冲区和临时缓冲区后立即解锁,然后进行数据复制操作,这样减少了锁的持有时间。
  2. 使用双缓冲区:使用两个缓冲区 buffer1_buffer2_,通过交换缓冲区实现双缓冲机制,减少锁竞争。生产者线程向 current_buffer_ 写入数据,而消费者线程从 temp_buffer_ 读取数据。

总结

通过实现和优化 BytesBuffer 类,我们可以方便地管理数据流,并确保在多线程环境下的安全性。

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

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

相关文章

【Linux】 在 Linux 中更换主机名

那年夏天我和你躲在 这一大片宁静的海 直到后来我们都还在 对这个世界充满期待 今年冬天你已经不在 我的心空出了一块 很高兴遇见你 让我终究明白 回忆比真实精彩 &#x1f3b5; 王心凌《那年夏天宁静的海》 在 Linux 系统中&#xff0c;更换主机名是系统…

使用Redis Lua脚本实现高级限流策略

引言 在现代的Web应用中&#xff0c;限流是一个非常重要的功能&#xff0c;它帮助我们控制对某些资源的访问频率&#xff0c;以防止系统过载和滥用。Redis是一个高性能的键值存储系统&#xff0c;它的原子操作和Lua脚本功能为实现复杂的限流策略提供了强大的支持。本文将详细介…

day50 1143.最长公共子序列 1035.不相交的线 53. 最大子序和 392.判断子序列

1143. 最长公共子序列 提示 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符的相对顺序的情况下删…

大腾智能,基于云原生的国产工业协同平台

大腾智能是一家基于云原生的国产工业软件与数字化协同平台&#xff0c;专注于推动企业数字化转型与升级&#xff0c;为企业提供一系列专业、高效的云原生数字化软件及方案&#xff0c;推动产品设计、生产及营销展示的革新&#xff0c;实现可持续发展。 大腾智能旗下产品 3D模型…

USB2.0学习4--USB包结构和包类型

目录 1. USB包基本结构 1.1 SOP域&#xff08;Start Of Packet&#xff09; 1.2 SYNC域&#xff08;同步域&#xff09; 1.3 PID域&#xff08;标识域&#xff09; 1.4 地址域&#xff08;ADDR&#xff09; 1.5 帧号域&#xff08;Fram&#xff09; 1.6 数据域&#xff…

前端也需要知道的一些常用linux命令

前端也需要知道的一些常用linux命令 1.问题背景2.连接工具&#xff08;SecureCRT_Portable&#xff09;a.下载工具b.连接服务器c.登录到root账户 3.基本命令a.cd命令和cd ..b.ll命令和ls命令c:cp命令d.rm命令e:rz命令f.unzip命令g.mv命令h.pwd命令&#xff08;这里没有用到&…

机器学习之支持向量机丨神经网络测试

选择题 SVM中的什么是支持向量&#xff1f; 【 正确答案: D】 A. 数据集中的所有样本 B. 模型参数 C. 模型的预测输出 D. 训练数据中离决策边界最近的样本点 支持向量机(SVM)算法的主要目标是&#xff1a; 【 正确答案: C】 A. 最小化间隔 B. 最小化损失函数 C. 最大化间隔 D.…

【LinuxC语言】TCPIP的经典5层结构

文章目录 前言TCP/IP的结构结构示意图结构的含义生活中的TCP/IP例子总结前言 TCP/IP,全称传输控制协议/因特网互联协议,是用于在互联网上进行数据交换的一组协议,形成了互联网的基础。TCP/IP的经典五层结构包括:物理层、数据链路层、网络层、传输层和应用层。这些层次各自…

CSS 相对父级固定,且不随滚动条滚动

CSS 相对父级固定&#xff0c;且不随滚动条滚动 <div class"parent"><div class"child-one">我是固定位置的子元素</div><div class"child-tow">我是滚动的子元素</div> </div>.parent {height: 200px; /*…

以正合,以奇胜,守正出奇,稳健

个人感觉说实话&#xff0c;在所里待的这几年&#xff0c;尤其是后两年&#xff0c;收获颇多&#xff0c;不管是智识上的&#xff0c;还有一堆兄弟&#xff0c;还有愿意分享和帮助我的老师们。 不管是搞科研还是做生意&#xff0c;稳健&#xff0c;在所里的时候&#xff0c;有…

Python-天天基金网爬虫分析

1.主题式网络爬虫名称&#xff1a;天天基金网爬虫分析 2.主题式网络爬虫爬取的内容与数据特征分析&#xff1a;通过访问天天基金的网站&#xff0c;爬取相对应的信息&#xff0c;最后保存下来做可视化分析。 3.主题式网络爬虫设计方案概述&#xff08;包括实现思路与技术难点…

益百分4.0版益生君重磅来袭,为您保驾护航

益百分4.0版益生君重磅来袭&#xff0c;为您保驾护航 暑期来临&#xff0c;很多人们终于等来了一年中最幸福的时刻&#xff0c;三五成群、结伴旅游成为他们选择欢度暑假的方式。 全国各地的旅游景点也迎来了旺季&#xff0c;各大旅游公司也推出了各种各样的旅游团购活动&#x…

FFmpeg交叉编译报错pkg-config not found

ffmpeg交叉编译时报错&#xff1a; WARNING: arm-linux-gnueabihf-pkg-config not found, library detection may fail.不慌&#xff0c;没有就下载嘛&#xff0c;直接install&#xff1a; sudo apt-get install pkg-config-arm-linux-gnueabihf 参考&#xff1a; How To I…

C++面试八股文:std::deque用过吗?

100编程书屋_孔夫子旧书网 某日二师兄参加XXX科技公司的C工程师开发岗位第26面&#xff1a; 面试官&#xff1a;deque用过吗&#xff1f; 二师兄&#xff1a;说实话&#xff0c;很少用&#xff0c;基本没用过。 面试官&#xff1a;为什么&#xff1f; 二师兄&#xff1a;因为使…

[学习笔记]3GPP R18宣布冻结,对物联网的影响是哪些?

6月18日&#xff0c;在上海举行的3GPP RAN&#xff08;无线接入网络项目&#xff09;第104次会议上&#xff0c;5G-A的第一代技术标准R18标准正式冻结。R18标准从立项到冻结历时3年多&#xff0c;是5G标准的第四版&#xff0c;也是面向5G-Advanced&#xff08;5G-A&#xff09;…

API-事件对象

学习目标&#xff1a; 掌握事件对象 学习内容&#xff1a; 获取事件对象事件对象常用属性trim方法案例 获取事件对象&#xff1a; 事件对象是什么 也是个对象&#xff0c;这个对象里有事件触发时的相关信息。 例如&#xff1a;鼠标点击事件中&#xff0c;事件对象就存了鼠标…

未来几年大多数人会面临的困境

未来几年&#xff0c;以下几个社会现象将会成为现实&#xff0c;希望这些相关行业的从业者早做准备&#xff0c;未雨绸缪。 一、就业难将会成为常态 就业将会越来越难、最近三年曾经如日中天的互联网企业在裁员降薪、曾经的用工大户也在裁员、不少倒闭破产的中小企业主也加入…

蓝牙ble数传芯片推荐,TD5327A芯片蓝牙5.1—拓达半导体

蓝牙数传芯片TD5327A芯片是一款支持蓝牙BLE的纯数传芯片&#xff0c;蓝牙5.1版本。芯片的亮点在于性能强&#xff0c;除了支持APP端直接对芯片做设置与查询操作&#xff0c;包括直接操作蓝牙芯片自身的IO与PWM口以外&#xff0c;还支持RTC日历功能&#xff0c;可以做各类定时类…

深度学习工具jupyter的new没有环境选项以及遇到的EnvironmentLocationNotFound:Not such a environment

jupyter安装使用 安装完Anaconda&#xff08;安装Anaconda具体请参考其他教程&#xff09;后&#xff0c;一般默认有安装jupyter打开 注意当前是base环境&#xff0c;后期使用jupyter需要切换环境 我们找到文件地址。用记事本打开 可以搜索&#xff1a;c.NotebookApp.noteb…

Redis规范

1 键值对的建议 1.1、key名建议&#xff1b; 建议key name设计&#xff1a;业务名:表名:id 比如&#xff1a; set school:student:1 martin 要求&#xff1a;不包含特殊字符 1.2、string 类型控制在10 KB以内&#xff0c;hash、list、set、zset元素个数不要超过5000&#…