C++并发编程 条件变量 condition_variable,线程安全队列示例
1. 背景
c++11中提供了对线程与条件变量的更好支持,对于写多线程程序方便了很多。
再看c++并发编程,记一下学习笔记。
2. c++11 提供的相关api
3.1 wait
wait用于无条件等待,其中Predicate表示校验条件,可以避免假唤醒。
unconditional (1)
void wait (unique_lock<mutex>& lck);
predicate (2)
template <class Predicate>
void wait (unique_lock<mutex>& lck, Predicate pred);
3.2 wait for
wait_for可以指定超时时间,其中Predicate表示校验条件,可以避免假唤醒。
unconditional (1)
template <class Rep, class Period>
cv_status wait_for (unique_lock<mutex>& lck,
const chrono::duration<Rep,Period>& rel_time);
predicate (2)
template <class Rep, class Period, class Predicate>
bool wait_for (unique_lock<mutex>& lck,
const chrono::duration<Rep,Period>& rel_time, Predicate pred);
3. 线程安全队列示例(生产者与消费者模型)
一个生产者向队列中添加数据;多个消费者从队列中读取任务。
#include <mutex>
#include <condition_variable>
#include <queue>
#include <vector>
#include <thread>
#include <iostream>
template<typename T>
class threadsafe_queue
{
private:
std::mutex mut;
std::queue<T> data_queue;
std::condition_variable data_cond;
public:
threadsafe_queue(){ }
void push(T new_value) {
std::lock_guard<std::mutex> lk(mut);
data_queue.push(new_value);
data_cond.notify_one();
}
//无限等待
int pop(T& value) {
std::unique_lock<std::mutex> lk(mut);
// (1) 带判断条件的wait, 条件不满足则继续等待; 满足则继续后续代码
data_cond.wait(lk,[this]{return !data_queue.empty();});
// (2)wait唤醒后需要再次判断, 避免假唤醒
//while(true){
// data_cond.wait(lk);
// if (data_queue.empty())
// continue;
// else
// break;
//}
value=data_queue.front();
data_queue.pop();
return 0;
}
//有限等待
int pop_with_timeout(T& value, int timeout) {
if (timeout < 0){
return this->pop(value);
}
std::unique_lock<std::mutex> lk(mut);
//带超时, 带判断条件的wait
data_cond.wait_for(lk, std::chrono::milliseconds(timeout), [this] {
std::cout << "thread id: " << std::this_thread::get_id() << " wait..." << std::endl;
return !data_queue.empty();}
);
if (!data_queue.empty()){
value=data_queue.front();
data_queue.pop();
return 0;
}
return -1;
}
bool is_empty(){
std::lock_guard<std::mutex> lk(mut);
return data_queue.empty();
}
};
template<typename T>
void consume(threadsafe_queue<T> &queue, bool &stop){
while(true){
if (stop && queue.is_empty()){ //结束条件
break;
}
int job_id = 0;
if (0 == queue.pop_with_timeout(job_id, 3)){
std::cout << "thread id: " << std::this_thread::get_id() << ", job:" << job_id << std::endl;
}
std::this_thread::sleep_for (std::chrono::milliseconds(5));
}
}
template<typename T>
void product(threadsafe_queue<T> &queue, bool &stop){
for (auto i = 0; i < 100; ++i){
queue.push(i);
std::this_thread::sleep_for (std::chrono::milliseconds(1));
}
stop = true; //设置结束条件
}
int main(){
threadsafe_queue<int> my_queue;
bool stop_flag = false;
//生产者
std::thread prod(product<int>, std::ref(my_queue), std::ref(stop_flag));
//消费者
std::vector<std::thread> cons;
for(auto i = 0; i < 5; ++i){
std::thread tmp = std::thread(consume<int>, std::ref(my_queue), std::ref(stop_flag));
cons.emplace_back(std::move(tmp));
}
prod.join();
for(auto &t : cons){
t.join();
}
return 0;
}
C++并发编程 条件变量 condition_variable,线程安全队列示例的更多相关文章
- Windows:C++11并发编程-条件变量(condition_variable)详解
<condition_variable >头文件主要包含了与条件变量相关的类和函数.相关的类包括 std::condition_variable和 std::condition_varia ...
- C++11并行编程-条件变量(condition_variable)详细说明
<condition_variable >头文件主要包含有类和函数相关的条件变量. 包括相关类 std::condition_variable和 std::condition_variab ...
- linux 条件变量与线程池
条件变量Condition Variables 概述 1. 条件变量提供了另外一种线程同步的方式.如果没有条件变量,程序需要使用线程连续轮询(可能在临界区critical section内)方式检查条 ...
- Java并发编程系列-(6) Java线程池
6. 线程池 6.1 基本概念 在web开发中,服务器需要接受并处理请求,所以会为一个请求来分配一个线程来进行处理.如果每次请求都新创建一个线程的话实现起来非常简便,但是存在一个问题:如果并发的请求数 ...
- [ 高并发]Java高并发编程系列第二篇--线程同步
高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...
- Java并发编程:如何创建线程?
Java并发编程:如何创建线程? 在前面一篇文章中已经讲述了在进程和线程的由来,今天就来讲一下在Java中如何创建线程,让线程去执行一个子任务.下面先讲述一下Java中的应用程序和进程相关的概念知识, ...
- 2、Java并发编程:如何创建线程
Java并发编程:如何创建线程? 在前面一篇文章中已经讲述了在进程和线程的由来,今天就来讲一下在Java中如何创建线程,让线程去执行一个子任务.下面先讲述一下Java中的应用程序和进程相关的概念知识, ...
- conditon_variable(条件变量)用于线程间同步
conditon_variable(条件变量)用于线程间同步 condition_variable有5个函数,函数名及对应的功能如下: wait阻塞自己,等待唤醒 wait_for阻塞自己,等待唤醒, ...
- Java并发编程系列-(7) Java线程安全
7. 线程安全 7.1 线程安全的定义 如果多线程下使用这个类,不过多线程如何使用和调度这个类,这个类总是表示出正确的行为,这个类就是线程安全的. 类的线程安全表现为: 操作的原子性 内存的可见性 不 ...
随机推荐
- react之异步请求数据,render先行渲染报错,未拿到数据
import React from 'react' import {connect} from 'react-redux' import { Redirect} from 'react-router- ...
- 将eclipse的maven项目导入到intellij idea中
最近项目中需要用到idea,需要将原来的eclipse项目进行转移.捣鼓了半天终于成功了,在这里和大家分享下,希望对大家有所帮助,如有错误,欢迎指正. idea的确是一款很智能的开发工具,真的是爱不释 ...
- JavaScript错误:Maximum call stack size exceeded错误
错误的表面意思是,因为递归次数太多而内存溢出, 当然引起溢出的原因很多 找了下问题来源,发现引用了两个版本的jquery,在layout.cshtml母模块页中和视图中都引用了jq.导致循环调用,从而 ...
- 扩展方法 C#
“扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型.” 定义和调用扩展方法 定义一个静态类以包含扩展方法. 该类必须对客户端代码可见. 有关可访问性规则 ...
- String:(字符串)中常用的方法
package stringyiwen; //字符串中常用的方法public class StringTest03 { public static void main(String[] args) { ...
- 微信h5支付源码DEMO参考
类库代码 wechatH5Pay.php <?php //use Flight; /** * 微信支付服务器端下单 * 微信APP支付文档地址: https://pay.weixin.qq.co ...
- Android开发之实现多次点击事件
在Android中给我们提供了单次点击事件.但并没有给我们提供双击,或者实现在一定时间内的多次事件.所以需要我们自己在单机监听上进行修改实现. 有如下两种实现方式: 1.定义一个存贮上一个第一次点击的 ...
- CDH搭建Hadoop集群(Centos7)
一.说明 节点(CentOS7.5) Server || Agent CPU node11 Server || Agent 4G node12 Agent 2G node13 Agent 2G 二 ...
- win10定时执行php脚本
转自http://www.cnblogs.com/wenhainan/p/6962089.html 第一步:确认windows上是否配置好了php环境变量,我用xampp安装的lamp环境,默认已经配 ...
- 「2017 山东一轮集训 Day7」逆序对
题解: 满满的套路题.. 首先显然从大到小枚举 然后每次生成的逆序对是1----(i-1)的 这样做dp是nk的 复杂度太高了 那我们转化一下问题 变成sigma(ai (ai<i) )= ...