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

posted @ 2022-03-06 11:44  秋雨声  阅读(165)  评论(0)    收藏  举报