基于c++11同步队列

同步队列-无锁队列-循环数组无锁队列.zip 配套代码讲解:https://blog.youkuaiyun.com/songchuwang1868/article/details/90200251 配套代码讲解:https://blog.youkuaiyun.com/songchuwang1868/article/details/90200251 配套代码讲解:https://blog.youkuaiyun.com/songchuwang1868/article/details/90200251 同步队列-无锁队列-循环数组无锁队列 同步队列-无锁队列-循环数组无锁队列 同步队列-无锁队列-循环数组无锁队列 立即下载

同步队列

介绍

实现过程

介绍

1.本篇文章旨在通过c++11新特新实现基本的参数模板化同步队列,此队列用以支持基本生产者、消费者应用
2.主要通过原子变量、条件变量、互斥锁、链表容器等实现
3.逐步实现此同步队列,并支持基本的生产者、消费者例程

实现过程

变量定义
// 引用使用到的标准库头文件
#include <atomic>              // c++11标准提供原子操作相关,可保证多线程数据访问的安全
#include <condition_variable>  // 条件变量,可用于实现多线程之间的同步操作
#include <list>                // 双向列表队列
#include <mutex>               // c++11标准提供的互斥锁,可用于多线程间数据访问保护操作

template <typename T>    // 参数类型模板化
class SyncQueue          // 同步队列类
{
    ...                  // 省略其它实现
private:
  std::condition_variable m_cv;  // 同步原语
  std::list<T> m_queue;          // 数据队列
  std::mutex m_mutex;            // 互斥锁,保护数据队列多线程访问
  std::atomic_bool m_stop;       // 停止队列,拒绝接收数据
};
成员函数
// 主要提供以下类成员函数
// SyncQueue、~SyncQueue、Push、Take、Stop、Size、IsEmpty等

SyncQueue() : m_stop(false) {}            // 构造函数
  virtual ~SyncQueue() { Stop(true); }    // 析构函数

  void Push(const T &v) {      // 添加数据到类内部数据队列
    if (m_stop)                // 停止添加数据
      return;

    {                          // 减小锁的粒度
      std::lock_guard<std::mutex> locker(m_mutex);   // 保护数据
      m_queue.emplace_back(v);                       // 添加数据
    }
    m_cv.notify_one();    // 通知任意一个其它同步阻塞的线程,有数据可读
  }
  void Push(T &&v) {      // 添加数据到类内部数据队列,形参以右值引用方式传输
    if (m_stop)
      return;

    {
      std::lock_guard<std::mutex> locker(m_mutex);
      m_queue.emplace_back(v);
    }
    m_cv.notify_one();
  }

  void Take(std::list<T> *ret) {     // 获取类内部队列数据,一次获取所有
    if (ret == nullptr)              // 判断是否空指针
        return;

    {
      std::unique_lock<std::mutex> locker(m_mutex);

      // 同步阻塞当前线程,当通知后唤醒线程,继续执行之后的流程,若lambda函数返回 false,则继续阻塞当前线程
      m_cv.wait(locker, [this] { return m_stop || !m_queue.empty(); });   
    }

    if (m_stop)
      return;

    std::lock_guard<std::mutex> locker(m_mutex);
    ret->swap(m_queue);    // 获取所有数据
  }
  void Take(T *ret) {      // 获取某一个数据
    if (ret == nullptr)
        return;

    {
      std::unique_lock<std::mutex> locker(m_mutex);
      m_cv.wait(locker, [this] { return m_stop || !m_queue.empty(); });
    }

    if (m_stop)
      return;

    std::lock_guard<std::mutex> locker(m_mutex);
    *ret = m_queue.front();           // 获取第一个数据
    m_queue.erase(m_queue.begin());   // 删除已获取的数据
  }

  bool Stop(bool stop) {   // 停止队列
    m_stop.store(stop);
    if (m_stop)
      m_cv.notify_all();   // 唤醒所有同步等待线程
  }
  int Size() {             // 获取队列数据数量
    std::lock_guard<std::mutex> locker(m_mutex);
    return m_queue.size();
  }
  bool IsEmpty() {         // 判断队列是否为空
    std::lock_guard<std::mutex> locker(m_mutex);
    return m_queue.empty();
  }
完整实现
// SyncQueue.hpp

#ifndef SYNCQUEUE_H
#define SYNCQUEUE_H

#include <atomic>
#include <condition_variable>
#include <list>
#include <mutex>

namespace que {

template <typename T> class SyncQueue {
public:
  SyncQueue() : m_stop(false) {}
  virtual ~SyncQueue() { Stop(true); }

  void Push(const T &v) {
    if (m_stop)
      return;

    {
      std::lock_guard<std::mutex> locker(m_mutex);
      m_queue.emplace_back(v);
    }
    m_cv.notify_one();
  }
  void Push(T &&v) {
    if (m_stop)
      return;

    {
      std::lock_guard<std::mutex> locker(m_mutex);
      m_queue.emplace_back(v);
    }
    m_cv.notify_one();
  }
  void Take(std::list<T> *ret) {
    if (ret == nullptr)
      return;

    {
      std::unique_lock<std::mutex> locker(m_mutex);
      m_cv.wait(locker, [this] { return m_stop || !m_queue.empty(); });
    }

    if (m_stop)
      return;

    std::lock_guard<std::mutex> locker(m_mutex);
    ret->swap(m_queue);
  }
  void Take(T *ret) {
    if (ret == nullptr)
      return;

    {
      std::unique_lock<std::mutex> locker(m_mutex);
      m_cv.wait(locker, [this] { return m_stop || !m_queue.empty(); });
    }

    if (m_stop)
      return;

    std::lock_guard<std::mutex> locker(m_mutex);
    *ret = m_queue.front();
    m_queue.erase(m_queue.begin());
  }

  bool Stop(bool stop) {
    m_stop.store(stop);
    if (m_stop)
      m_cv.notify_all();
  }
  int Size() {
    std::lock_guard<std::mutex> locker(m_mutex);
    return m_queue.size();
  }
  bool IsEmpty() {
    std::lock_guard<std::mutex> locker(m_mutex);
    return m_queue.empty();
  }

private:
  std::condition_variable m_cv;
  std::list<T> m_queue;
  std::mutex m_mutex;
  std::atomic_bool m_stop;
};

} // namespace que

#endif // SYNCQUEUE_H

}
例程
  • 生产者、消费者模式,数据同步
#include "SyncQueue.hpp"
#include <thread>
#include <chrono>
#include <iostream>

void TestSyncQueue() {
  que::SyncQueue<int> sync;
  std::thread t1([&sync] {
    thread_local int i = 0;
    while (true) {
      sync.Push(std::move(i++));
      std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }
  });

  std::thread t2([&sync] {
    int val = -1;
    while (true) {
      sync.Take(&val);
      std::cout << val << " - " << std::this_thread::get_id() << std::endl;
      std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }
  });

  std::thread t3([&sync] {
    int val = -1;
    while (true) {
      sync.Take(&val);
      std::cout << val << " - " << std::this_thread::get_id() << std::endl;
      std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }
  });

  std::thread t4([&sync] {
    int val = -1;
    while (true) {
      sync.Take(&val);
      std::cout << val << " - " << std::this_thread::get_id() << std::endl;
      std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }
  });

  t1.join();
  t2.join();
  t3.join();
  t4.join();
}

int main(int argc, char *argv[]) {
  TestSyncQueue();
  return 0;
}

输出结果:

0 - 139746321880640

1 - 139746330273344

2 - 139746313487936

3 - 139746321880640

4 - 139746330273344

5 - 139746330273344

6 - 139746321880640

7 - 139746321880640

8 - 139746330273344

9 - 139746313487936

10 - 139746321880640

  • 异步任务模式

#include "SyncQueue.hpp"
#include <functional>
...

using Task = std::function<void()>;   // 函数包装器,抽象任务类型
class ExecuteTask final {
public:
  ...

  void Push(const Task &task) {
    m_queue.Push(task);
  }
  void Push(Task &&task) {
    m_queue.Push(task);
  }

private:
  que::SyncQueue<Task> m_queue;

  // std::thread* m_thread;   // 此处使用线程或线程池,同步等待任务,异步执行
};

起始

在x86机器上运行jailhouse jailhouse jaihouse提供了一个demo ,https://github.com/siemens/jailhouse-images可以用于编译一整套可用的demo。 适用于多个平台。编译过程主要参考https://blog.youkuaiyun.com/weixin_39541632/article/details/110422345 此demo可以生成多个平台所用的操作系统image。 ... 阅读详情

相关推荐

MATLAB下pdf文件操作读取示例

当遇到一些需要大量数据的项目,数据的读取与储存显得尤为重要。怎样把数据从其他格式的文件中读取,并运用到程序中是很多时候我们要解决的问题。对于平常的.txt,和.xlsx文件,MATLAB有对应的函数帮助读取,但是遇到pdf文件时MATLAB很难读取内容。本文以一个操作实例提供了一个从pdf文件中读取数据的方法。

UESTC 五高考3模拟的博客 6558

C++11的半同步半异步线程池

半同步半异步线程池用的比较多,实现也比较简单。其中同步层包括同步服务层和排队层,指的是将接收的任务排队,将所有的任务排队到一个队列中,等待处理;异步层指多个线程处理任务,异步处理层从同步层取出任务,并发处理任务。

weixin_44477424的博客 1151

最全卷积总结篇(分组、深度可分离、空洞、转置等)

分组卷积(Group Convolution)是一种卷积操作方式,它最早在AlexNet中引入,并在深度学习中被广泛使用,尤其是在高效模型设计(如MobileNet和ResNeXt)中。分组卷积通过将输入特征通道分为若干组,并在每组内单独进行卷积操作,可以减少计算复杂度和参数量,同时有效利用模型的结构特性。分组卷积的工作原理通道分组:输入特征图的通道图为C_in,输出特征图的通道数为C_out,将每组的C_in和C_out分为G组,每组的通道数为C_in/G和C_out/G。组内卷积。

qq_44815135的博客 4219

C++ 队列基础知识

1.队列的定义队列是一种先进先出的线性结构,通常用于存储和管理那些需要按照特定顺序处理的元素。2.为什么要使用队列有序性:由于队列具有先进先出的特性,它能够保证数据元素的顺序性,这对于很多需要按照特 定顺序处理数据的应用场景非常重要。缓存管理:在计算机科学中,队列常用作缓存管理,如CPU任务调度、网络中的数据包排队等。异步处理。

2301_80210302的博客 2135

告别游戏卡关!用Cheat Engine 7.5修改单机游戏数据的保姆级教程(附Tutorial靶场练习)

本文提供了一份详细的Cheat Engine 7.5使用教程,帮助玩家轻松修改单机游戏数据。从基础操作到高级技巧,包括精确值扫描、模糊扫描、指针扫描和代码注入,教程还涵盖了《植物大战僵尸》和《星露谷物语》的实战案例,确保玩家能够安全、高效地优化游戏体验。

weixin_30082367的博客 784

VS2022离线安装总闪退?可能是这个--noWeb参数没加对(完整参数指南)

本文深入解析了VS2022离线安装过程中常见的闪退问题,指出核心原因往往在于命令行参数使用不当,特别是`--noWeb`参数。文章提供了完整的参数使用指南和实战解决方案,包括证书处理、安装器文件修复及自动化脚本,帮助用户彻底解决离线部署中的验证失败与闪退难题。

weixin_28842269的博客 758

【c++】【线程池】同步队列

是基于 半同步/半异步模式 设计实现的 任务Task是一个模板。

m0_64014551的博客 1504

【QT开发教程】使用Qt进行NFC编程

近场通信(NFC,Near Field Communication)技术广泛应用于现代设备中,例如智能手机、支付终端和门禁系统。Qt提供了一套完整的NFC模块,使开发者可以轻松地在应用程序中实现NFC功能。本文将介绍如何在Qt中进行NFC编程,包括基本概念、使用方法以及一些实际的示例。

科技改变人类,技术成就未来 1469

【图文并茂】c++介绍之队列

队列(queue)简称队,它也是一种操作受限的线性表,其限制为仅允许在表的一端进行插入操作,而在表的另一端进行删除操作队尾(rear) :进行插入的一端队首(front):进行删除的一端入队(enqueue):插入新元素出队(dequeue):删除新元素队列是一种先进先出表(FIFO),而前面介绍过的栈是一种先进后出表。(一个队列)

m0_73421035的博客 6617

基于 InceptionNeXt 模块增强的 YOLOv8 模型:针对多尺度目标检测的改进与实现

modules.py。

know_F0727的博客 205

渗透测试之哥斯拉实战

可以直接在这里使用meterpreter命令进行对服务端的控制。选择目标 - 添加,配置连接信息,之后测试连接成功!php的shell功能如图。先要进行数据库的配置信息。可以直接在这里打包全站。

大河之犬的博客 2488

C++ 实现一个消息队列

消息队列在多线程的场景有时会用到,尤其是线程通信跨线程调用的时候,就可以使用消息队列进行通信。C++实现一个能用的消息队列还是比较简单的,只需要一个队列一个互斥变量和一个条件变量,这些在标准库中都有提供。基于曾经写过的项目,总结出来最简单的消息队列的实现将在下文中介绍。

codeofcc的博客 1万+

PCIE2.0/PCIE3.0/PCIE4.0/PCIE5.0接口的带宽、速率计算

一、PCIE接口速率: 二、PCIE相关概念: 传输速率为每秒传输量GT/s,而不是每秒位数Gbps,因为传输量包括不提供额外吞吐量的开销位; 比如 PCIe 1.x和PCIe 2.x使用8b / 10b编码方案,导致占用了20% (= 2/10)的原始信道带宽。 GT/s —— Giga transation per second (千兆传输/秒),即每一秒内传输的次数。重点在于描述物理层通信协议的速率属性,可以不和链路宽度等关联。 Gbps —— Giga Bits Per Second

技术联盟 1万+

C++11 同步阻塞队列

参考《深入应用C++11》 SyncQueue.cpp //同步阻塞队列 #include "SyncQueue.h" using namespace std; template<class T> SyncQueue<T>::SyncQueue(int max_size):max_size(max_size)//这里注意类不能少了类型SyncQueue<T&...

djqueen的博客 1万+

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

【网络编程】半同步--半异步线程池源码分析之任务队列(基于C++11)

前言对于C++的学习,感觉如果只看书,学习效率很低。很多新知识新概念理解起来都很困难,而C++11更是引入了更多新的概念和知识。而在学习服务端这部分,什么“同步–异步”也把人搞得很晕 如果看不懂书,看不懂概念,不如就找个例子分析一下,起码能让你快速上手。 想起了老陈给我们上《操作系统》时讲的要把理论和实例化的东西相结合,对于我这种笨笨的娃尤其适宜,只有理论实在看不懂ToT。本文主要通过一个实

康康的博客 1722

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

C++11多线程thread,实现同步队列

封装thread-实现多线程,join,detach

weixin_43199441的博客 665

C++11多线程编程:从生产者-消费者问题到同步队列实现

在多线程编程中,生产者-消费者模型是解决线程间数据交换的核心设计模式,它通过同步机制确保数据的安全传递。其原理基于互斥锁和条件变量的协同工作,互斥锁保护共享数据免受竞争条件影响,而条件变量则实现线程间的等待与通知机制,从而避免忙等待。这一模式的技术价值在于解耦生产与消费过程,提升系统吞吐量和响应性,是构建高性能服务器、日志系统和实时数据处理流水线等并发应用的基础。在C++11标准中,std::mutex和std::condition_variable为实现线程安全的同步队列提供了直接支持,使得开发者能够基于

weixin_30768881的博客 225

C++11同步队列实现:生产者-消费者模型的高效线程安全解决方案

在多线程编程中,线程同步是确保数据一致性和程序正确性的核心机制。其原理是通过互斥锁、条件变量等原语协调线程间的执行顺序和数据访问。C++11标准库首次将std::mutex、std::condition_variable等并发组件纳入标准,为编写可移植的高性能并发程序提供了基础。这些技术的核心价值在于,它们能有效解决数据竞争和竞态条件问题,是构建健壮并发系统的基石。其典型应用场景广泛存在于网络服务器、任务调度器和数据处理流水线中,用于实现高效的生产者-消费者模式。本文聚焦于利用C++11特性,从零构建一个具

weixin_33462927的博客 345

C++11同步队列实现:多线程生产者消费者模型的核心组件

在并发编程中,线程安全的数据交换是核心挑战。生产者消费者模型通过解耦生产与消费过程,有效协调不同速度的线程协作。其实现原理依赖于互斥锁保证操作的原子性,条件变量实现高效线程同步,避免忙等待。这一机制的技术价值在于提升系统吞吐量、防止数据竞争与死锁,是高并发服务器、日志系统、线程池等场景的基石。本文聚焦于C++11标准库,利用std::mutex和std::condition_variable,结合智能指针与移动语义,实现了一个高效、健壮的同步队列,并深入探讨了其在高并发场景下的应用与优化。

weixin_29213655的博客 239

C++11的条件变量

C++11的条件变量

qq_25048473的博客 633

探索高效数据管理新境界:cpp_redis,C++世界的轻量级Redis客户端

在高速发展的现代应用开发中,数据处理的效率与灵活性成为了决定项目成功与否的关键。因此,我们为您介绍一款强大的工具——`cpp_redis`,一个专为C++11设计的异步多平台轻量级Redis客户端,旨在简化与Redis数据库的交互过程,提升数据操作的效率。 ## 项目介绍 `cpp_redis`以其对C++11标准的支持,以及零依赖的设计理念脱颖而出,为开发者提供了一种简洁高效的解决方案来集成...

gitblog_00750的博客 347

c++回调函数、同步队列、生产者消费者举例

C++11 同步队列、注册回调函数、生产者消费者代码记录 同步队列: // data queue template <typename T> class SynchronizedQueue { public: SynchronizedQueue() : queue_() , mutex_() , cond_() , request_to_end_(false) , enqueue_data_(true)

qq_29022265的博客 2732

c++ 同步阻塞队列

参考:《C++11深入应用》 用同步阻塞队列解决生产者消费者问题。 生产者消费者问题: 有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个有多个缓冲区的缓冲池, 生产者将它生产的产品放入一个缓冲区中,消费者可以从缓冲区中取走产品进行消费,所有生产者和消费者都是异步方式运行的,但它们必须保持同步, 即不允许消费者到一个空...

weixin_30666401的博客 134

基于C++11的多线程同步安全队列,支持多读端多写端

【代码】基于C++11的多线程同步安全队列。

猿不倒的专栏 441

如何用C++11+标准库构建高性能线程安全队列?同步机制实战案例详解

掌握C++多线程同步机制,构建高性能线程安全队列。适用于高并发场景,结合std::mutex与std::condition_variable实现高效同步,提升程序稳定性与吞吐量。详解设计思路与优化技巧,值得收藏。

ProceGlow的博客 784

C++11半同步半异步线程池

在处理大量并发任务的时候,如果按照传统的方法一个请求一个线程来处理请求任务,线程的创建和销毁将消耗过多的系统资源,还增加了线程上下文切换的开销,线程池技术可以很好的解决这些问题,线程池技术通过在系统中预先创建一定数量的线程,当任务请求到来的时候从线程池中分配一个预先创建的线程去处理任务,线程在处理完任务以后还可以重用,通过线程池能避免大量的线程创建和摧毁动作线程池分为半同步半异步线程池和领导者追随者线程池,本文主要通过C++11实现一个半同步半异步的线程池 半同步半异步的线程池分为3层: 第一层是同步服务层

guicaifjz的博客 579

用C++11实现一个有界的阻塞队列

对于一个无界的阻塞队列而言,其实现非常简单,即用一个锁(锁队列)+ 一个条件变量(判空)即可。那么对于一个有界阻塞队列而言,其队列的容量有上限,其实只要再加一个条件变量用来判断是否满即可。 综上,我们需要 mutex: 保护队列的读写操作 notEmptyCV: 条件变量,在take时wait, 在put之后notify notFullCV: 条件变量, 在put时wait, 在take之后notify. C++11提供了丰富的多线程编程库,包括加锁解锁、同步原语等封装。我的实现如下: #prag

翻肚鱼儿的博客 721
上一篇: std::queue
下一篇: 设计模式---设计原则
无夜_
博客等级 码龄7年 2916粉丝 51原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值