boost 对于多线程应用的优化
多线程的应用开发,不管是客户端还是服务端都是能够极高提高性能的。如今CPU都是多核就更应该利用起来,但是不合理的代码会造成死锁宕机等,必须要注意以下几点:
1,多个子线程之间执行的逻辑最好是独立的,互不干涉的
2,子线程使用对象池创建销毁数据一定要加锁
3,子线程与主线程对同一数据尽量避免同时操作,如果不确定就需要加锁
4,线程之间的数据交互最好使用队列投递
现在我主要说的是跨线程队列,一般是使用加锁来保证队列数据正确,boost 增加了无锁队列,原理是使用原子操作队列交换,效率比使用锁的队列高很多
1 #pragma once 2 #pragma warning(disable:4996) 3 4 #include <boost/thread/mutex.hpp> 5 //#define USE_LIST 6 7 #ifndef USE_LIST 8 #include <queue> 9 template<class T> 10 class enable_queue : public std::queue<T> 11 { 12 public: 13 void clear() 14 { 15 std::queue<T>::c.clear(); 16 } 17 18 bool pop(T& v) 19 { 20 v = std::queue<T>::front(); 21 std::queue<T>::pop(); 22 return true; 23 } 24 }; 25 26 template<class T> 27 class enable_safe_queue : public std::queue<T> 28 { 29 public: 30 void clear() 31 { 32 std::queue<T>::c.clear(); 33 } 34 35 bool pop(T& v) 36 { 37 v = std::queue<T>::front(); 38 std::queue<T>::pop(); 39 return true; 40 } 41 42 void safe_pop(T& v) 43 { 44 boost::lock_guard<boost::mutex> lock(m_mutex); 45 this->pop(v); 46 } 47 48 void safe_push(T& v) 49 { 50 boost::lock_guard<boost::mutex> lock(m_mutex); 51 std::queue<T>::push(v); 52 } 53 54 void safe_swap(enable_queue<T> q) 55 { 56 boost::lock_guard<boost::mutex> lock(m_mutex); 57 swap(q); 58 } 59 60 private: 61 boost::mutex m_mutex; 62 }; 63 64 #else 65 #include <list> 66 67 template<class T> 68 class enable_queue : public std::list<T> 69 { 70 public: 71 bool pop(T& v) 72 { 73 v = front(); 74 erase(begin()); 75 return true; 76 } 77 78 void push(T& v) 79 { 80 push_back(v); 81 } 82 }; 83 84 template<class T> 85 class enable_safe_queue : public std::queue<T> 86 { 87 public: 88 bool pop(T& v) 89 { 90 v = front(); 91 erase(begin()); 92 return true; 93 } 94 95 void push(T& v) 96 { 97 push_back(v); 98 } 99 100 void safe_pop(T& v) 101 { 102 boost::lock_guard<boost::mutex> lock(m_mutex); 103 pop(v); 104 } 105 106 void safe_push(T& v) 107 { 108 boost::lock_guard<boost::mutex> lock(m_mutex); 109 push(v); 110 } 111 112 void safe_swap(enable_safe_queue<T> q) 113 { 114 boost::lock_guard<boost::mutex> lock(m_mutex); 115 swap(q); 116 } 117 private: 118 boost::mutex m_mutex; 119 }; 120 121 #endif 122 123 124 125 #include <boost/lockfree/queue.hpp> 126 #include <boost/lockfree/spsc_queue.hpp> 127 #include <boost/atomic.hpp> 128 //无锁线程安全队列 129 130 template<class T> 131 class fast_safe_queue : public boost::lockfree::spsc_queue<T> 132 { 133 public: 134 //queue必须先定义队列数量 过大会初始化很慢 135 fast_safe_queue(uint16_t maxqueue = std::numeric_limits<uint16_t>::max()) 136 :boost::lockfree::spsc_queue<T>(maxqueue) 137 { 138 139 } 140 ~fast_safe_queue() 141 { 142 //clear(); 143 } 144 145 146 //必须在停止使用后调用 否则无法完全清理掉 147 void clear() 148 { 149 T temp; 150 while(!boost::lockfree::spsc_queue<T>::empty()) 151 { 152 if(!boost::lockfree::spsc_queue<T>::pop(temp)) 153 break; 154 } 155 } 156 }; 157 158 template<class T> 159 class fast_count_queue : public boost::lockfree::spsc_queue<T> 160 { 161 public: 162 //queue必须先定义队列数量 过大会初始化很慢 163 fast_count_queue(uint16_t maxqueue = std::numeric_limits<uint16_t>::max()) 164 :boost::lockfree::spsc_queue<T>(maxqueue),m_count(0) 165 { 166 167 } 168 ~fast_count_queue() 169 { 170 //clear(); 171 } 172 173 //必须在停止使用后调用 否则无法完全清理掉 174 void clear() 175 { 176 T temp; 177 while(!boost::lockfree::spsc_queue<T>::empty()) 178 { 179 if(!safe_pop(temp)) 180 break; 181 } 182 } 183 184 bool safe_pop(T& v) 185 { 186 if(boost::lockfree::spsc_queue<T>::pop(v)) 187 { 188 m_count--; 189 return true; 190 } 191 return false; 192 } 193 194 bool safe_push(const T& v) 195 { 196 if(boost::lockfree::spsc_queue<T>::push(v)) 197 { 198 m_count++; 199 return true; 200 } 201 return false; 202 } 203 204 int size() 205 { 206 return m_count; 207 } 208 209 private: 210 boost::atomic_int m_count; 211 }; 212 213 //释放资源时可能出问题 214 template<class T> 215 class fast_mutli_queue : public boost::lockfree::queue<T> 216 { 217 public: 218 //queue必须先定义队列数量 过大会初始化很慢 219 fast_mutli_queue(uint16_t maxqueue = std::numeric_limits<uint16_t>::max()) 220 :boost::lockfree::queue<T>(maxqueue) 221 { 222 223 } 224 ~fast_mutli_queue() 225 { 226 //clear(); 227 } 228 229 230 //必须在停止使用后调用 否则无法完全清理掉 231 void clear() 232 { 233 T temp; 234 while(!boost::lockfree::queue<T>::empty()) 235 { 236 if(!boost::lockfree::queue<T>::pop(temp)) 237 break; 238 } 239 } 240 };
对于boost的线程池推荐使用threadpool,可以自己在网上找到源代码,需要少量修改,注意在退出时有个线程未退出导致的内存泄露的BUG