(原创)C++ 同步队列
(原创)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++ 同步队列的更多相关文章
- JAVA多线程经典问题 -- 生产者 消费者 同步队列实现方法
在JAVASE5 中的java.util.concurrent.BlockingQueue支持,BlockingQueue是一个接口但是我们通常可以使用LinkedBlockingQueue,它是一个 ...
- Java并发包之同步队列SynchronousQueue理解
1 简介 SynchronousQueue是这样一种阻塞队列,其中每个put必须等待一个take,反之亦然.同步队列没有任何内部容量,甚至连一个队列的容量都没有.不能在同步队列上进行peek,因为仅在 ...
- 【转载】阻塞队列之三:SynchronousQueue同步队列 阻塞算法的3种实现
一.SynchronousQueue简介 Java 6的并发编程包中的SynchronousQueue是一个没有数据缓冲的BlockingQueue,生产者线程对其的插入操作put必须等待消费者的移除 ...
- AbstractQueuedSynchronizer同步队列与Condition等待队列协同机制
概要: AQS维护了一个同步队列 Condition是JUC的一个接口,AQS的ConditionObject实现了这个接口,维护了一个等待队列(等待signal信号的队列) 线程调用reentran ...
- 【死磕Java并发】-----J.U.C之AQS:CLH同步队列
此篇博客全部源代码均来自JDK 1.8 在上篇博客[死磕Java并发]-–J.U.C之AQS:AQS简单介绍中提到了AQS内部维护着一个FIFO队列,该队列就是CLH同步队列. CLH同步队列是一个F ...
- 阻塞队列之三:SynchronousQueue同步队列 阻塞算法的3种实现
一.SynchronousQueue简介 Java 6的并发编程包中的SynchronousQueue是一个没有数据缓冲的BlockingQueue,生产者线程对其的插入操作put必须等待消费者的移除 ...
- CLH同步队列
原文链接:https://blog.csdn.net/chenssy/article/details/60781148 AQS内部维护着一个FIFO队列,该队列就是CLH同步队列. CLH同步队列是一 ...
- 关于Pyhton多线程同步队列的应用
''' 同步队列 put方法和task_done方法, queue有一个未完成任务数量num,put依次num+1, task依次num-1.任务都完成时任务结束. 1.创建一个 Queue.Queu ...
- 并发编程-concurrent指南-阻塞队列-同步队列SynchronousQueue
SynchronousQueue:同步Queue,属于线程安全的BlockingQueue的一种,此队列设计的理念类似于"单工模式",对于每个put/offer操作,必须等待一个t ...
随机推荐
- 使用Kubeadm安装Kubernetes【单Master节点】
参考:Kubernetes官方文档 Kubernetes安装方案选择 Centos 7 配置科学上网 安装Calico网络插件 kubernetes-dashboard部署 Kubernetes ...
- python之提升程序性能的解决方案
Python在性能方面不卓越,但是使用一些小技巧,可以提高Python程序的性能,避免不必要的资源浪费. 1. 使用局部变量 尽可能使用局部变量替代全局变量,可以是程序易于维护并且有助于提高性能节约成 ...
- C/C++函数调用时传参过程与可变参数实现原理
C/C++函数调用时传参过程与可变参数实现原理 C语言的经典swap问题 在学习C语言的时候,我们大都遇到过一些经典例题,这些经典例题背后所代表的是往往是C/C++背后的一些运行原理,比如下面这个示例 ...
- 数据结构中的堆(Heap)
堆排序总结 这是排序,不是查找!!!查找去找二叉排序树等. 满二叉树一定是完全二叉树,但完全二叉树不一定是满二叉树. 构建顶堆: a.构造初始堆 b.从最后一层非叶节点开始调整,一直到根节点 c.如果 ...
- [原创]VBA实现汇总excel,将多个Excel文件内容复制到一个Excel文件中
功能:遍历用户指定的文件夹,把文件夹中所有的excel文件的第一个表格的数据复制到本excel文件中.注意,每个excel文件中有效数据行的判断标准是A列的最后一个有数据的单元格的行号,比如A列到第1 ...
- hive的常用函数工作总结
1.concat_ws 它是一个特殊形式的 CONCAT() concat_ws(分隔符,参数1,参数2.......) as 字段 2.split 返回值为一个数组 a.基本用法: 例1:split ...
- Windows Automation API 3.0 Overview
https://www.codemag.com/article/0810042 While general accessibility requirements (such as font color ...
- PHP - Filters
Retrieve the administrator password of this application. 对文件包含的介绍------------第一个链接需要谷歌 https://mediu ...
- read函数和write函数
read 函数 inline int read() { ,f=; char c=getchar(); ; c=getchar();} +c-'; c=getchar();} return f*x; } ...
- MongoDB shell 0 集合方法
方法名 描述 db.collection.aggregate() 聚合,主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果 db.collection.bulkWrite() 批量写入 ...