(原创)C++ 同步队列

同步队列作为一个线程安全的数据共享区,经常用于线程之间数据读取,比如半同步半异步线程池的同步队列。

其实做起来比较简单,要用到list、锁和条件变量,条件变量的作用是在队列满了或者空了的时候等待通知。先看一个简单的同步队列:

 
#include <thread>
#include <condition_variable>
#include <mutex>
#include <list>
#include <iostream>
using namespace std; template<typename T>
class SimpleSyncQueue
{
public:
void Put(const T& x)
{
std::lock_guard<std::mutex> locker(m_mutex);
m_queue.push_back(x);
m_notEmpty.notify_one();
} void Take(T& x)
{
std::unique_lock<std::mutex> locker(m_mutex);
m_notEmpty.wait(locker, [this]{return !m_queue.empty();});
x = m_queue.front();
m_queue.pop_front();
} private:
std::list<T> m_queue;
std::mutex m_mutex;
std::condition_variable_any m_notEmpty;
};
 

再看一个带上限的同步队列:

 
#include<list>
#include<mutex>
#include<thread>
#include<condition_variable>
#include <iostream>
using namespace std; template<typename T>
class SyncQueue
{
public:
SyncQueue(int maxSize) :m_maxSize(maxSize), m_needStop(false)
{
} void Put(const T&x)
{
Add(x);
} void Put(T&&x)
{
Add(std::forward<T>(x));
} void Take(std::list<T>& list)
{
std::unique_lock<std::mutex> locker(m_mutex);
m_notEmpty.wait(locker, [this]{return m_needStop || NotEmpty(); }); if (m_needStop)
return;
list = std::move(m_queue);
m_notFull.notify_one();
} void Take(T& t)
{
std::unique_lock<std::mutex> locker(m_mutex);
m_notEmpty.wait(locker, [this]{return m_needStop || NotEmpty(); }); if (m_needStop)
return;
t = m_queue.front();
m_queue.pop_front();
m_notFull.notify_one();
} void Stop()
{
{
std::lock_guard<std::mutex> locker(m_mutex);
m_needStop = true;
}
m_notFull.notify_all();
m_notEmpty.notify_all();
} bool Empty()
{
std::lock_guard<std::mutex> locker(m_mutex);
return m_queue.empty();
} bool Full()
{
std::lock_guard<std::mutex> locker(m_mutex);
return m_queue.size() == m_maxSize;
} size_t Size()
{
std::lock_guard<std::mutex> locker(m_mutex);
return m_queue.size();
} int Count()
{
return m_queue.size();
}
private:
bool NotFull() const
{
bool full = m_queue.size() >= m_maxSize;
if (full)
cout << "full, waiting,thread id: " << this_thread::get_id() << endl;
return !full;
} bool NotEmpty() const
{
bool empty = m_queue.empty();
if (empty)
cout << "empty,waiting,thread id: " << this_thread::get_id() << endl;
return !empty;
} template<typename F>
void Add(F&&x)
{
std::unique_lock< std::mutex> locker(m_mutex);
m_notFull.wait(locker, [this]{return m_needStop || NotFull(); });
if (m_needStop)
return; m_queue.push_back(std::forward<F>(x));
m_notEmpty.notify_one();
} private:
std::list<T> m_queue; //缓冲区
std::mutex m_mutex; //互斥量和条件变量结合起来使用
std::condition_variable m_notEmpty;//不为空的条件变量
std::condition_variable m_notFull; //没有满的条件变量
int m_maxSize; //同步队列最大的size bool m_needStop; //停止的标志
};
 

测试代码比较简单,就不写了。实际的运用在后面的线程池中会用到。

一点梦想:尽自己一份力,让c++的世界变得更美好!

(原创)C++ 同步队列的更多相关文章

  1. JAVA多线程经典问题 -- 生产者 消费者 同步队列实现方法

    在JAVASE5 中的java.util.concurrent.BlockingQueue支持,BlockingQueue是一个接口但是我们通常可以使用LinkedBlockingQueue,它是一个 ...

  2. Java并发包之同步队列SynchronousQueue理解

    1 简介 SynchronousQueue是这样一种阻塞队列,其中每个put必须等待一个take,反之亦然.同步队列没有任何内部容量,甚至连一个队列的容量都没有.不能在同步队列上进行peek,因为仅在 ...

  3. 【转载】阻塞队列之三:SynchronousQueue同步队列 阻塞算法的3种实现

    一.SynchronousQueue简介 Java 6的并发编程包中的SynchronousQueue是一个没有数据缓冲的BlockingQueue,生产者线程对其的插入操作put必须等待消费者的移除 ...

  4. AbstractQueuedSynchronizer同步队列与Condition等待队列协同机制

    概要: AQS维护了一个同步队列 Condition是JUC的一个接口,AQS的ConditionObject实现了这个接口,维护了一个等待队列(等待signal信号的队列) 线程调用reentran ...

  5. 【死磕Java并发】-----J.U.C之AQS:CLH同步队列

    此篇博客全部源代码均来自JDK 1.8 在上篇博客[死磕Java并发]-–J.U.C之AQS:AQS简单介绍中提到了AQS内部维护着一个FIFO队列,该队列就是CLH同步队列. CLH同步队列是一个F ...

  6. 阻塞队列之三:SynchronousQueue同步队列 阻塞算法的3种实现

    一.SynchronousQueue简介 Java 6的并发编程包中的SynchronousQueue是一个没有数据缓冲的BlockingQueue,生产者线程对其的插入操作put必须等待消费者的移除 ...

  7. CLH同步队列

    原文链接:https://blog.csdn.net/chenssy/article/details/60781148 AQS内部维护着一个FIFO队列,该队列就是CLH同步队列. CLH同步队列是一 ...

  8. 关于Pyhton多线程同步队列的应用

    ''' 同步队列 put方法和task_done方法, queue有一个未完成任务数量num,put依次num+1, task依次num-1.任务都完成时任务结束. 1.创建一个 Queue.Queu ...

  9. 并发编程-concurrent指南-阻塞队列-同步队列SynchronousQueue

    SynchronousQueue:同步Queue,属于线程安全的BlockingQueue的一种,此队列设计的理念类似于"单工模式",对于每个put/offer操作,必须等待一个t ...

随机推荐

  1. prometheus学习系列十: Prometheus AlertManager配置文件说明

    alertmanager配置文件说明 alertmanager是通过命令行标记和配置文件配置的,命令行标记配置不可变的系统参数,配置文件定义抑制规则.通知路由和通知接收器.可以通过官方提供的routi ...

  2. 【转】UCOSIII基础知识点

    1.其中最有用的功能应该是时间片轮转法( roundrobin), 这个是 uC/OS-II 中不支持的,但是现在已经是 uC/OS-III 的一个功能了 2.uC/OS-III 被设计用于 32 位 ...

  3. 开机没有deepin启动项的解决办法

    增加efi/deepin/grubx64.efi的启动项 问题描述 打开电脑,进入bios没有deepin启动项 解决办法 进入bios setup,选择boot sourquense,选择uefi, ...

  4. C/C++解题常用STL大礼包 含vector,map,set,queue(含优先队列) ,stack的常用用法

    每次忘记都去查,真难啊 /* C/C++解题常用STL大礼包 含vector,map,set,queue(含优先队列) ,stack的常用用法 */ /* vector常用用法 */ //头文件 #i ...

  5. 如何显示隐藏的文件在win7系统中

    点左下角“开始”菜单,再点击“计算机”. 点击窗口顶部靠左位置的“组织”菜单,选择其中的“文件夹和搜索选项”. 在弹出的窗口里点击切换到“查看”选项卡.   在窗口中部位置下拉滚动条,找到“显示隐藏的 ...

  6. 项目Beta冲刺(团队)--4/7

    课程名称:软件工程1916|W(福州大学) 作业要求:项目Beta冲刺 团队名称:葫芦娃队 作业目标:进行新一轮的项目冲刺,尽力完成并完善项目 团队博客 队员学号 队员昵称 博客地址 04160242 ...

  7. CodeForces - 1051E :Vasya and Big Integers(Z算法 & DP )

    题意:给定字符串S,A,B.现在让你对S进行切割,使得每个切割出来的部分在[A,B]范围内,问方案数. 思路:有方程,dp[i]=Σ dp[j]   (S[j+1,i]在合法范围内).    假设M和 ...

  8. 关于Python文件读写

    Python中文件操作可以通过open函数,这的确很像C语言中的fopen.通过open函数获取一个file object,然后调用read(),write()等方法对文件进行读写操作. 1.open ...

  9. Dart 库预览

    容导航 dart:core - numbers, collections, strings, and more dart:async - asynchronous programming dart:m ...

  10. react 沉思录

    react = Virtual DOM + component + data flow + jsx 核心是Virtual DOM结构的状态维护.渲染机制及UI系统的DOM组织功能: 基于Virtual ...