C++并发编程 条件变量 condition_variable,线程安全队列示例
2018-06-23 23:49
633 查看
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++ 11 并发: 正确 的使用条件变量-condition_variable
- boost::condition_variable 设计c++ 生产者消费者队列
- boost::condition_variable 设计c++ 生产者消费者队列
- Java并发编程利用 Condition 实现阻塞队列
- boost::condition_variable 设计c++ 生产者消费者队列
- boost::condition_variable 设计c++ 生产者消费者队列
- c++ 11 多线线程系列--------使用锁和条件变量的线程安全队列
- C++11 使用 unique_lock,lock_guard,condition_variable, lambda表达式实现线程安全队列
- boost::condition_variable 设计c++ 生产者消费者队列
- 【JAVA并发编程实战】12、使用condition实现多线程下的有界缓存先进先出队列
- C++ 并发编程,std::unique_lock与std::lock_guard区别示例
- 并发编程(一): POSIX 使用互斥量和条件变量实现生产者/消费者问题
- 用c++11的bind,function,boost::condition_variable实现的一个线程安全的任务队列
- 第十四节: 介绍四大并发集合类并结合单例模式下的队列来说明线程安全和非安全的场景及补充性能调优问题。
- 0038 Java学习笔记-多线程-传统线程间通信、Condition、阻塞队列、《疯狂Java讲义 第三版》进程间通信示例代码存在的一个问题
- Python tornado队列示例-一个并发web爬虫代码分享
- C++——并发编程
- Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition
- 并发编程--synchronized示例(一)