Mutex和Lock

=================================版权声明=================================

版权声明:原创文章 禁止转载 

请通过右侧公告中的“联系邮箱(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('
');
 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('
');
 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 }

运行结果

原文地址:https://www.cnblogs.com/wlsandwho/p/13840532.html