无界队列

#include<queue>
#include<mutex>
#include<condition_variable>
#include<optional>
#include<cassert>
#include<thread> template<typename T,typename Container = std::queue<T>>
class Queue //无界队列
{
public:
Queue() = default;
~Queue() = default; //禁止拷贝和移动,编译器会自动delete
/*Queue(const Queue&) = delete;
Queue(Queue&&) = delete;
Queue& operator=(const Queue&) = delete;
Queue& operator=(Queue&&) = delete;*/ void push(const T& val)
{
emplace(val);
} void push(T&& val)
{
emplace(std::move(val));
} template<typename...Args>
void emplace(Args&&...args)
{
std::lock_guard lk{ mtx_ };
q_.push(std::forward<Args>(args)...);
cv_.notify_one();
} T pop()//阻塞
{
std::unique_lock lk{ mtx_ };
cv_.wait(lk, [this] {return !q_.empty(); });//如果队列不为空就继续执行,否则阻塞
assert(!q_.empty());
T ret{ std::move_if_noexcept(q_.front()) };
q_.pop();
return ret;
} std::optional<T> try_pop()//非阻塞
{
std::unique_lock lk{ mtx_ };
if (q_.empty())return {};
std::optional<T> ret{ std::move_if_noexcept(q_.front()) };
q_.pop();
return ret;
}
bool empty()const
{
std::lock_guard lk{ mtx_ };
return q_.empty();
}
private:
Container q_;
mutable std::mutex mtx_;
std::condition_variable cv_;
}; #include<iostream>
int main()
{
Queue<int>q;
std::thread t1(
[&] {
for (int i = 0; i < 100; ++i)
{
q.push(i);
}
}); std::thread t2(
[&] {
for (int i = 0; i < 100; ++i)
{
//std::cout<<q.pop()<<" ";
if (auto ret = q.try_pop())
{
std::cout << *ret<<" ";
}
}
});
t1.join();
t2.join();
return 0;
}

有界队列

#include<mutex>
#include<condition_variable>
#include<boost/circular_buffer.hpp>
#include<optional> template<typename T>
class Queue
{
public:
Queue(size_t capacity) :q_{ capacity } {} template<typename T>
void push(T&& val)//阻塞
{
std::unique_lock lk{ mtx_ };
not_full_.wait(lk, [this] {return !q_.full(); });
assert(!q_.full());
q_.push_back(std::forward<T>(val));
not_empty_.notify_one();
} template<typename T>
bool try_push(T&& val)//非阻塞
{
std::lock_guard lk{ mtx_ };
if (q_.full())return false;
q_.push_back(std::forward<T>(val));
not_empty_.notify_one();
return true;
} T pop()//阻塞
{
std::unique_lock lk{ mtx_ };
not_empty_.wait(lk, [this] {return !q_.empty(); });
asert(!q_.empty());
T ret{ std::move_if_noexcept(q_.front()) };
q_.pop_front();
not_full_.notify_one();
return ret; }
std::optional<T> try_pop()//非阻塞
{
std::lock_guard lk{ mtx_ };
if (q_.empty())return {};
std::optional<T> ret{ std::move_if_noexcept(q_.front()) };
q_.pop_front();
not_full_.notify_one();
return ret;
} private:
boost::circular_buffer<T>q_;
std::mutex mtx_;
std::condition_variable not_full_;
std::condition_variable not_empty_;
}; #include<iostream>
int main()
{
Queue<int>q{10};
std::thread t1(
[&] {
for (int i = 0; i < 100;)
{
if (q.try_push(i))
{
i++;
}
}
}); std::thread t2(
[&] {
for (int i = 0; i < 100;)
{
//std::cout<<q.pop()<<" ";
if (auto ret = q.try_pop())
{
std::cout << *ret << " ";
++i;
}
}
});
t1.join();
t2.join();
return 0;
}

C++ 线程安全的队列的更多相关文章

  1. (转)java自带线程池和队列详细讲解 - CSDN过天的专栏

    一简介 线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的.在jdk1.5之后这一情况有了很大的改观.Jdk1.5之后加入了java.util ...

  2. java自带线程池和队列详细讲解

    Java线程池使用说明 一简介 线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的.在jdk1.5之后这一情况有了很大的改观.Jdk1.5之后 ...

  3. 深入浅出Win32多线程设计之MFC的多线程-线程与消息队列(经典)

    1.创建和终止线程 在MFC程序中创建一个线程,宜调用AfxBeginThread函数.该函数因参数不同而具有两种重载版本,分别对应工作者线程和用户接口(UI)线程. 工作者线程 CWinThread ...

  4. Java线程:堵塞队列与堵塞栈

    一.堵塞队列 Java定义了堵塞队列的接口java.util.concurrent.BlockingQueue,堵塞队列是一个指定长度的队列,当试图向队列中添加元素而队列已满,或者是想从队列移出元素而 ...

  5. python端口扫描用多线程+线程安全的队列+Thread类实现

    用线程安全的队列Queue实现扫描端口数据存储 用多线程扫描端口 用Thread类实现程序组织 #coding:utf-8 import sys import socket import sys im ...

  6. c/c++ 多线程 利用条件变量实现线程安全的队列

    多线程 利用条件变量实现线程安全的队列 背景:标准STL库的队列queue是线程不安全的. 利用条件变量(Condition variable)简单实现一个线程安全的队列. 代码: #include ...

  7. 线程中的队列(queue)

    队列的类型和常用方法 队列是一种数据结构,它类似于列表.但列表是线程不安全的,而队列是线程安全的. python的queue(python3,python2为Queue)提供了3种队列: Queue: ...

  8. java线程自带队列的使用以及线程阻塞

    java线程,设置队列的大小实现队列阻塞 public class QueueThreads { private static int nThreads = 4;//Runtime.getRuntim ...

  9. Java自带线程池和队列详解

    Java线程池使用说明 一简介 线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的.在jdk1.5之后这一情况有了很大的改观.Jdk1.5之后 ...

  10. java自带线程池和队列详细讲解<转>

    Java线程池使用说明 一简介 线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的.在jdk1.5之后这一情况有了很大的改观.Jdk1.5之后 ...

随机推荐

  1. C++ 析构函数的调用顺序

    如果指针指向基类,但是指针在运行时指向派生类,则该基类必须具有虚拟析构函数,以便破坏派生类.如果没有虚拟析构函数,则只会运行基类的析构函数. 比如: Base* basePtr; basePtr = ...

  2. LayUI样式优化

    如下是LayUI框架中页面元素的CSS优化样式: /* 表单输入框宽度 */ .layui-form-item .layui-input-inline { width: 295px; } /* 下拉框 ...

  3. Jenkins流水线使用@Grab 导入Maven库

    有个需求需要在pipeline中调用Java的SDK去执行业务 使用 @Grab 注解可以在Maven中导入Java 库, @Grab('org.apache.commons:commons-math ...

  4. django学习第三天---django模板渲染,过滤器,反向循环 reversed,自定义标签和过滤器,模板继承

    django模板渲染 模板渲染,模板指的就是html文件,渲染指的就是字符串替换,将模板中的特殊符号替换成相关数据 基本语法 {{ 变量 }} {% 逻辑 %} 变量使用 示例 Views.py文件 ...

  5. Linux开端---Centos

    Linux-Centos 虚拟化所需工具:https://pan.baidu.com/s/1643-kYcx9oPGnGEZM1pLOw?pwd=g0v5 提取码:g0v5 问题解决 正常注册网络适配 ...

  6. 第一百一十二篇: JS数组Array(一)数组基本用法

    好家伙,   1.数组 Array应该就是ECMAScript中最常用的类型了.ECMAScript数组跟其他编程语言的数组有很大区别. 跟其他语言中的数组一样,ECMAScript 数组也是一组有序 ...

  7. Linux Cheat Sheet

  8. 【Azure API 管理】APIM关闭开发者门户的办法

    问题描述 APIM默认提供了开发者门户,可以让用户体验如何来调用接口.但如果不想开发这个功能的情况下,是否有办法关闭呢? 问题解答 答案是:开发人员门户是没有办法关闭的.但是作为另一种的代替方案,如自 ...

  9. [Python] 协程学习过程

    开始 ​ 之前一直在做那个rProxy的项目,后来发现,服务端不用协程或者异步编程这样的手段是不行的,最主要的问题就是对于每个http请求都对应一个线程,这个开销非常大.对于一个网页而言,四五十个ht ...

  10. (一)Git 学习之为什么要学习 Git

    一.版本控制 1.1 何为版本控制 版本控制(Revision control)是一种在开发的过程中用于管理我们对文件.目录或工程等内容的修改历史,方便查看更改历史记录.备份,以便恢复以前的版本的软件 ...