c++线程安全的多线程
1 #pragma once 2 3 //可控长度、pop、push的启停 线程安全队列 4 5 #include <atomic> 6 #include <condition_variable> 7 //#include <functional> 8 #include <memory> 9 #include <mutex> 10 #include <queue> 11 12 #include <iostream> 13 namespace safe_queue_length 14 { 15 template <class T> 16 class Queue 17 { 18 public: 19 Queue(const size_t size_max) 20 :_size_max(size_max) { 21 _quit = ATOMIC_VAR_INIT(false); 22 _finished = ATOMIC_VAR_INIT(false); 23 } 24 25 bool push(T& data) 26 { 27 std::unique_lock<std::mutex> lock(_mutex); 28 while (!_quit && !_finished) 29 { 30 if (_queue.size() < _size_max) 31 { 32 _queue.push(std::move(data)); 33 //_queue.push(data); 34 //_emptyQue.notify_all();//适用一对一 两个线程 35 _emptyQue.notify_one(); 36 return true; 37 } 38 else 39 { 41 _fullQue.wait(lock); 42 } 43 } 44 45 return false; 46 } 47 48 49 bool pop(T& data) 50 { 51 std::unique_lock<std::mutex> lock(_mutex); 52 while (!_quit) 53 { 54 if (!_queue.empty()) 55 { 56 //data = std::move(_queue.front()); 57 data = _queue.front(); 58 _queue.pop(); 59 _fullQue.notify_one(); 60 return true; 61 } 62 else if (_queue.empty() && _finished) 63 { 64 return false; 65 } 66 else 67 { 68 _emptyQue.wait(lock); 69 } 70 } 71 return false; 72 } 73 /* 74 * 从队列中弹出一个元素,如果队列为空返回false 75 * */ 76 bool try_pop(T& data) 77 { 78 std::lock_guard<std::mutex>lk(_mutex); 79 if (_queue.empty()) 80 return false; 81 82 data = _queue.front(); 83 _queue.pop(); 84 return true; 85 } 86 // The queue has finished accepting input 87 void finished()//push finish 88 { 89 _finished = true; 90 _emptyQue.notify_all(); 91 } 92 93 void quit()//pop quit 94 { 95 _quit = true; 96 _emptyQue.notify_all(); 97 _fullQue.notify_all(); 98 } 99 100 int length() 101 { 102 return static_cast<int>(_queue.size()); 103 } 104 105 bool isEmpty() 106 { 107 std::lock_guard<std::mutex>lk(_mutex); 108 return _queue.empty(); 109 } 110 111 private: 112 // Data 113 std::queue<T> _queue; 114 //std::queue<T>::size_type _size_max; 115 typename std::queue<T>::size_type _size_max; 116 117 // Thread gubbins 118 std::mutex _mutex; 119 std::condition_variable _fullQue; 120 std::condition_variable _emptyQue; 121 122 // Exit 123 // 原子操作 124 std::atomic_bool _quit; //{ false };比加锁效率高 125 std::atomic_bool _finished; // { false }; 126 }; 127 }
使用方法:
1 safe_queue_length::Queue<uint32_t> len_queue(100); 2 void Produce(uint32_t num) 3 { 4 for (uint32_t i = 0;i < num; ++i) 5 { 6 len_queue.push(i); 7 } 8 } 9 10 void Consume(uint32_t num) 11 { 12 while (!len_queue.isEmpty()) 13 { 14 uint32_t outnum = 0; 15 len_queue.pop(outnum); 16 std::cout << outnum << std::endl; 17 } 18 } 19 20 int main() 21 { 22 int n = 10; 23 std::thread thd_produce(Produce, 20); 24 std::thread thd_consume(Consume,std::ref(n)); 25 26 // 27 while (1); 28 return 0; 29 }
详情请参考:https://github.com/jincike/CPP-NormalSkills/tree