=================================版权声明=================================
版权声明:原创文章 禁止转载
请通过右侧公告中的“联系邮箱(wlsandwho@foxmail.com)”联系我
勿用于学术性引用。
勿用于商业出版、商业印刷、商业引用以及其他商业用途。
本文不定期修正完善。
本文链接:https://www.cnblogs.com/wlsandwho/p/13840532.html
耻辱墙:http://www.cnblogs.com/wlsandwho/p/4206472.html
=======================================================================
C++ 异步
=======================================================================
mutex
使用lock锁定,使用unlock解锁。
使用lock_guard在作用域内自动对mutex加锁和解锁。(基于RAII)
使用try_lock尝试加锁,成功后需要unlock。
使用try_lock尝试加锁,成功后使用带adopt_lock的lock_guard接管。
timed_mutex
使用try_lock_for尝试在时间段内阻塞等待锁,超时则退出等待。(这个我不感兴趣不写例子了)
使用try_lock_until尝试在到某时间点之前一直阻塞等待锁,超过该时间点则退出等待。(这个我不感兴趣不写例子了)
recursive_mutex
可以多次加锁,当有1次解锁时就释放锁。
timed_recursive_mutex
使用try_lock_for尝试在时间段内阻塞等待锁,超时则退出等待。(这个我不感兴趣不写例子了)
使用try_lock_until尝试在到某时间点之前一直阻塞等待锁,超过该时间点则退出等待。(这个我不感兴趣不写例子了)
std::lock
同时锁住多个锁
std::try_lock
同事尝试锁住多个锁
unique_lock
(这个此处不是重点,应当和Condition Variable配合使用,先不写例子了)
1 #include <iostream> 2 #include <future> 3 #include <functional> 4 5 class CTestA 6 { 7 public: 8 void Do0(std::string& str) 9 { 10 for (auto c : str) 11 { 12 std::cout.put(c); 13 } 14 15 std::cout.put('\n'); 16 } 17 18 void Do1(std::string& str) 19 { 20 std::lock_guard<std::mutex> lg(mtx); 21 22 for (auto c:str) 23 { 24 std::cout.put(c); 25 } 26 27 std::cout.put('\n'); 28 } 29 30 protected: 31 std::mutex mtx; 32 }; 33 34 void TestA0() 35 { 36 //演示,当没有互斥量进行同步时,输出可能会被打乱。 37 38 std::string strHello("This_is_a_lock_guard_demo."); 39 CTestA oTA; 40 41 //由于是类成员函数调用了复杂的参数(string),所以这里用std::bind作为第二个参数。当然可以用lambda但我不喜欢。 42 //strHello可能需要std::ref,这里省略了因为不是本节主要内容。 43 auto fA01 = std::async(std::launch::async, std::bind(&CTestA::Do0, &oTA, strHello)); 44 auto fA02 = std::async(std::launch::async, std::bind(&CTestA::Do0, &oTA, strHello)); 45 46 fA01.get(); 47 fA02.get(); 48 } 49 50 void TestA1() 51 { 52 //演示,当有互斥量进行同步时,输出正常。 53 54 std::string strHello("This_is_a_lock_guard_demo."); 55 CTestA oTA; 56 57 auto fA11 = std::async(std::launch::async, std::bind(&CTestA::Do1, &oTA, strHello)); 58 auto fA12 = std::async(std::launch::async, std::bind(&CTestA::Do1, &oTA, strHello)); 59 60 fA11.get(); 61 fA12.get(); 62 } 63 64 class CTestB 65 { 66 public: 67 void Do01() 68 { 69 std::lock_guard<std::mutex> lg(mtx); 70 std::cout << "Do01()" << std::endl; 71 } 72 73 void Do02() 74 { 75 std::lock_guard<std::mutex> lg(mtx); 76 77 std::cout << "Do02()...begin" << std::endl; 78 Do01(); 79 std::cout << "Do02()...end" << std::endl; 80 } 81 82 void Do11() 83 { 84 std::lock_guard<std::recursive_mutex> lg(rmtx); 85 86 std::cout << "Do11()" << std::endl; 87 } 88 89 void Do12() 90 { 91 std::lock_guard<std::recursive_mutex> lg(rmtx); 92 93 std::cout << "Do12()...begin" << std::endl; 94 Do11(); 95 std::cout << "Do12()...end" << std::endl; 96 } 97 98 protected: 99 std::mutex mtx; 100 std::recursive_mutex rmtx; 101 }; 102 103 void TestB0() 104 { 105 CTestB oB0; 106 oB0.Do02();//未使用递归互斥量时,嵌套调用,引发异常。 107 } 108 109 void TestB1() 110 { 111 CTestB oB0; 112 oB0.Do12();//使用递归互斥量,嵌套调用,正常运行。 113 oB0.Do11();//能够够正常运行。 114 } 115 116 class CTestC 117 { 118 public: 119 void Do01() 120 { 121 mtx.lock(); 122 std::cout << "Do01()...lock" << std::endl; 123 } 124 void Do02() 125 { 126 mtx.unlock(); 127 std::cout << "Do02()...unlock" << std::endl; 128 } 129 130 void Do11() 131 { 132 if (mtx.try_lock()) 133 { 134 std::cout << "Do11()...try_lock" << std::endl; 135 136 mtx.unlock(); 137 std::cout << "Do11()...unlock" << std::endl; 138 } 139 else 140 { 141 std::cout << "Do11()...try_lock failed" << std::endl; 142 } 143 } 144 void Do12() 145 { 146 if (mtx.try_lock()) 147 { 148 std::cout << "Do12()...try_lock,use adopt_lock" << std::endl; 149 150 std::lock_guard<std::mutex> lg(mtx, std::adopt_lock);//采用了mtx之前的状态,并在作用域结束后释放mtx 151 } 152 else 153 { 154 std::cout << "Do12()...try_lock failed" << std::endl; 155 } 156 } 157 protected: 158 std::mutex mtx; 159 }; 160 161 void TestC1() 162 { 163 //此处使用单一线程模拟多线程时交错执行的情形 164 CTestC oTC; 165 166 ////////////////////////////////////////////////////////////////////////// 167 //失败的情形 168 169 //使用mutex的try_lock功能,并用unlock释放。 170 oTC.Do01(); 171 oTC.Do11(); 172 oTC.Do02(); 173 std::cout << "-----------" << std::endl; 174 175 //使用mutex的try_lock功能,使用带adopt_lock的lock_guard接管。 176 oTC.Do01(); 177 oTC.Do12(); 178 oTC.Do02(); 179 std::cout << "-----------" << std::endl; 180 181 ////////////////////////////////////////////////////////////////////////// 182 //成功的情形 183 184 oTC.Do11();//使用mutex的try_lock功能,并用unlock释放。 185 std::cout << "-----------" << std::endl; 186 187 oTC.Do12();//使用mutex的try_lock功能,使用带adopt_lock的lock_guard接管。 188 std::cout << "-----------" << std::endl; 189 } 190 191 class CTestD 192 { 193 public: 194 void Do01() 195 { 196 std::lock_guard<std::mutex> lg1(mtx1); 197 std::cout << "Do01 Get mtx1" << std::endl; 198 std::this_thread::sleep_for(std::chrono::seconds(1)); 199 200 std::lock_guard<std::mutex> lg2(mtx2); 201 std::cout << "Do01 Get mtx2" << std::endl; 202 std::this_thread::sleep_for(std::chrono::seconds(2)); 203 } 204 205 void Do02() 206 { 207 std::lock_guard<std::mutex> lg2(mtx2); 208 std::cout << "Do02 Get mtx2" << std::endl; 209 std::this_thread::sleep_for(std::chrono::seconds(2)); 210 211 std::lock_guard<std::mutex> lg1(mtx1); 212 std::cout << "Do02 Get mtx1" << std::endl; 213 } 214 215 void Do03() 216 { 217 std::lock_guard<std::mutex> lg2(mtx2); 218 std::cout << "Do03 Get mtx2" << std::endl; 219 std::this_thread::sleep_for(std::chrono::seconds(5)); 220 } 221 222 void Do11() 223 { 224 std::lock(mtx1, mtx2); 225 std::lock_guard<std::mutex> lg1(mtx1, std::adopt_lock); 226 std::lock_guard<std::mutex> lg2(mtx2, std::adopt_lock); 227 std::cout << "Do11 Get mtx1 mtx2" << std::endl; 228 std::this_thread::sleep_for(std::chrono::seconds(2)); 229 230 } 231 232 void Do12() 233 { 234 std::lock(mtx2,mtx1); 235 std::lock_guard<std::mutex> lg2(mtx2, std::adopt_lock); 236 std::lock_guard<std::mutex> lg1(mtx1, std::adopt_lock); 237 std::cout << "Do12 Get mtx2 mtx1" << std::endl; 238 std::this_thread::sleep_for(std::chrono::seconds(2)); 239 } 240 241 void Do21() 242 { 243 int idx=std::try_lock(mtx1, mtx2); 244 if (idx<0) 245 { 246 std::lock_guard<std::mutex> lg2(mtx2, std::adopt_lock); 247 std::lock_guard<std::mutex> lg1(mtx1, std::adopt_lock); 248 std::cout << "Do21 Get mtx1 mtx2" << std::endl; 249 } 250 else 251 { 252 std::cout << "Do21 did not get "<<idx+1 << std::endl; 253 } 254 } 255 256 protected: 257 std::mutex mtx1; 258 std::mutex mtx2; 259 }; 260 261 void TestD01() 262 { 263 //Do01与Do02的顺序相反造成死锁 264 CTestD oTD; 265 auto f01 = std::async(std::launch::async, &CTestD::Do01, &oTD); 266 auto f02 = std::async(std::launch::async, &CTestD::Do02, &oTD); 267 f01.get(); 268 f02.get(); 269 } 270 271 void TestD02() 272 { 273 //Do01过了很久才拿到所有的锁 274 CTestD oTD; 275 auto f01 = std::async(std::launch::async, &CTestD::Do01, &oTD); 276 auto f03 = std::async(std::launch::async, &CTestD::Do03, &oTD); 277 f01.get(); 278 f03.get(); 279 } 280 281 void TestD11() 282 { 283 //避免了死锁 284 285 CTestD oTD; 286 auto f01 = std::async(std::launch::async, &CTestD::Do02, &oTD); 287 auto f11 = std::async(std::launch::async, &CTestD::Do11, &oTD); 288 f01.get(); 289 f11.get(); 290 } 291 292 void TestD12() 293 { 294 //避免了死锁 295 296 CTestD oTD; 297 auto f11 = std::async(std::launch::async, &CTestD::Do11, &oTD); 298 auto f12 = std::async(std::launch::async, &CTestD::Do12, &oTD); 299 f11.get(); 300 f12.get(); 301 } 302 303 void TestD21() 304 { 305 //try_lock 306 307 CTestD oTD; 308 auto f03 = std::async(std::launch::async, &CTestD::Do03, &oTD); 309 auto f21 = std::async(std::launch::async, &CTestD::Do21, &oTD); 310 f03.get(); 311 f21.get(); 312 } 313 314 int main() 315 { 316 std::cout << "-----------A0-------------" << std::endl; 317 TestA0(); 318 std::cout << "-----------A1-------------" << std::endl; 319 TestA1(); 320 321 std::cout << "-----------B0-------------" << std::endl; 322 //TestB0();//发生异常 323 std::cout << "-----------B1-------------" << std::endl; 324 TestB1(); 325 326 std::cout << "-----------C1-------------" << std::endl; 327 TestC1(); 328 329 std::cout << "-----------D01-------------" << std::endl; 330 //TestD01();//死锁 331 std::cout << "-----------02" << std::endl; 332 TestD02(); 333 std::cout << "-----------11" << std::endl; 334 TestD11(); 335 std::cout << "-----------12" << std::endl; 336 TestD12(); 337 std::cout << "-----------21" << std::endl; 338 TestD21(); 339 340 std::cout << "-----------End-------------" << std::endl; 341 return 0; 342 }
运行结果