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 线程安全的定义 如果多线程下使用这个类,不过多线程如何使用和调度这个类,这个类总是表示出正确的行为,这个类就是线程安全的. 类的线程安全表现为: 操作的原子性 内存的可见性 不 ...
随机推荐
- MariaDB和mySQL到底区别在哪,实验说明问题!
先看图,插入数据和时间的对数图,实验条件一直且关闭了mysql默认事务保证不是单条事务而是批量事务 另外确保了mysql and mariaDB都是在支持事务存储引擎下测试的. MySQL之父Wide ...
- 在 laravel 的 DB::transaction 中,为外部变量赋值
例如,我想在 laravel 的事务中,对某个外部变量赋值,然后在后续的逻辑中判断该变量的属性 $user = null; // init DB::transaction(function() use ...
- 【深度探索C++对象模型 | 02】构造函数语意学
默认构造函数的构造操作.拷贝构造函数额构造操作 注意:默认构造函数和拷贝构造函数在必要时的时候由编译器产生出来. 参考资料 关于默认构造函数的几个错误认识(四种情况下,编译器会生成默认构造函数)
- hdu 1005 根据递推公式构造矩阵 ( 矩阵快速幂)
f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7. Sample Input1 1 3 //a b n1 2 100 0 0 ...
- HashTable、HashMap、ConcurrentHashMap的区别
HashTable是做了同步的,HashMap未考虑同步.所以HashMap在单线程情况下效率较高:HashTable在的多线程情况下,同步操作能保证程序执行的正确性. HashMap是非线程安全的, ...
- POJ 1064 1759 3484 3061 (二分搜索)
POJ 1064 题意 有N条绳子,它们长度分别为Li.如果从它们中切割出K条长度相同的绳子的话,这K条绳子每条最长能有多长?答案保留小数点后2位. 思路 二分搜索.这里要注意精度问题,代码中有详细说 ...
- 【AtCoder】ARC078
C - Splitting Pile 枚举从哪里开始分的即可 #include <bits/stdc++.h> #define fi first #define se second #de ...
- Codeforces Round #228 (Div. 1)
今天学长给我们挂了一套Div.1的题,难受,好难啊. Problem A: 题目大意:给你n个数字,让你叠成n堆,每个数字上面的数的个数不能超过这个数,如 3 上面最多放三个数字 问你,最少能放几堆. ...
- Python dict get items pop update
一.get方法 dict = {'k1':1,'k2':2} dict.get('k1') 1 dict.get('k2') 2 dict.get('k3') None dict.get('k3',' ...
- 023 SpringMVC拦截器
一:拦截器的HelloWorld 1.首先自定义拦截器 只要实现接口就行. package com.spring.it.interceptors; import javax.servlet.http. ...