c/c++ 多執行緒 利用條件變數實現執行緒安全的佇列
阿新 • • 發佈:2018-11-19
多執行緒 利用條件變數實現執行緒安全的佇列
背景:標準STL庫的佇列queue是執行緒不安全的。
利用條件變數(Condition variable)簡單實現一個執行緒安全的佇列。
程式碼:
#include <queue> #include <memory> #include <mutex> #include <condition_variable> #include <iostream> #include <thread> template<typename T> class threadsave_queue{ private: mutable std::mutex mut;//必須是mutable,因為empty是const方法,但是要鎖mut,鎖操作就是改變操作 std::queue<T> data_queue; std::condition_variable data_cond; public: threadsave_queue(){} threadsave_queue(threadsave_queue const& other){ std::lock_guard<std::mutex> lk(other.mut); data_queue = other.data_queue(); } void push(T new_value){ std::lock_guard<std::mutex> lk(mut); data_queue.push(new_value); data_cond.notify_one(); } void wait_and_pop(T& value){ std::unique_lock<std::mutex> lk(mut); data_cond.wait(lk, [this]{return !data_queue.empty();}); value = data_queue.front(); data_queue.pop(); } std::shared_ptr<T> wait_and_pop(){ std::unique_lock<std::mutex> lk(mut); data_cond.wait(lk, [this]{return !data_queue.empty();}); std::shared_ptr<T> res(std::make_shared<T>(data_queue.front())); data_queue.pop(); return res; } bool empty()const{ std::lock_guard<std::mutex> lk(mut); return data_queue.empty(); } }; void make_data(threadsave_queue<int>& tq, int val){ tq.push(val); } void get_data1(threadsave_queue<int>& tq, int& d1){ tq.wait_and_pop(d1); } void get_data2(threadsave_queue<int>& tq, int& d1){ auto at = tq.wait_and_pop(); d1 = *at; } int main(){ threadsave_queue<int> q1; int d1; std::thread t1(make_data, std::ref(q1), 10); std::thread t2(get_data1, std::ref(q1),std::ref(d1)); t1.join(); t2.join(); std::cout << d1 << std::endl; std::thread t3(make_data, std::ref(q1), 20); std::thread t4(get_data2, std::ref(q1),std::ref(d1)); t3.join(); t4.join(); std::cout << d1 << std::endl; q1.empty(); }
編譯方法:
g++ -g XXX.cpp -std=c++11 -L/home/ys/Downloads/boost_1_68_0/stage/lib -lboost_thread -lboost_system -pthread
編譯或者執行有問題的,請參考多執行緒 boost編譯與執行的坑