经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
<二>线程间互斥-mutex互斥锁和lock_guard
来源:cnblogs  作者:Hello_Bugs  时间:2022/12/12 16:07:23  对本文有异议

多线程程序
竞态条件:多线程程序执行的结果是一致的,不会随着CPU对线程不同的调用顺序而产生不同的运行结果.

解决?:互斥锁 mutex

经典的卖票问题,三个线程卖100张票

代码1

  1. #include <iostream>
  2. #include <thread>
  3. #include <list>
  4. #include <mutex>
  5. int ticketCount = 100;
  6. std::mutex mtx;//互斥锁
  7. void sellTicket(int window) {
  8. while (ticketCount > 0) {
  9. mtx.lock();
  10. std::cout << "窗口" << window << "销售" << ticketCount << std::endl;
  11. ticketCount--;
  12. mtx.unlock();
  13. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  14. }
  15. }//end
  16. int main() {
  17. std::list<std::thread> tlist;
  18. for (int i = 0; i < 3; i++) {
  19. tlist.push_back(std::thread(sellTicket,i));
  20. }
  21. for (std::thread & t : tlist) {
  22. t.join();
  23. }
  24. system("pause");
  25. return 0;
  26. }

上面代码的问题...

  1. while (ticketCount > 0) {
  2. mtx.lock();
  3. std::cout << "窗口" << window << "销售" << ticketCount << std::endl;
  4. ticketCount--;
  5. mtx.unlock();
  6. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  7. }
  8. 如果ticketCount =1 ,当前有一个线程A while (ticketCount > 0)为true,线程A还没执行ticketCount--完成时,cpu交给了线程B
  9. 线程B while (ticketCount > 0)也为true,进入 循环体内,造成了买0号票,改进如下

代码2

  1. #include <iostream>
  2. #include <thread>
  3. #include <list>
  4. #include <mutex>
  5. int ticketCount = 100;
  6. std::mutex mtx;//互斥锁
  7. void sellTicket(int window) {
  8. while (ticketCount > 0) {
  9. mtx.lock();
  10. if(ticketCount >0){
  11. std::cout << "窗口" << window << "销售" << ticketCount << std::endl;
  12. ticketCount--;
  13. }
  14. mtx.unlock();
  15. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  16. }
  17. }//end
  18. int main() {
  19. std::list<std::thread> tlist;
  20. for (int i = 0; i < 3; i++) {
  21. tlist.push_back(std::thread(sellTicket,i));
  22. }
  23. for (std::thread & t : tlist) {
  24. t.join();
  25. }
  26. system("pause");
  27. return 0;
  28. }

代码2还有些问题!! 如下

  1. mtx.lock();
  2. 代码
  3. 代码
  4. 代码
  5. 代码
  6. .....
  7. mtx.unlock();
  8. 如果在代码lock()和unlock()之间 非常返回,导致mtx没有正常unlock(),那么出现死锁问题 =》智能指针 lock_gurad unique_lock

看lock_gurad

  1. #include <iostream>
  2. #include <thread>
  3. #include <list>
  4. #include <mutex>
  5. int ticketCount = 100;
  6. std::mutex mtx;//互斥锁
  7. void sellTicket(int window) {
  8. while (ticketCount > 0) {
  9. {
  10. std::lock_guard<std::mutex> lock(mtx);
  11. std::cout << "窗口" << window << "销售" << ticketCount << std::endl;
  12. ticketCount--;
  13. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  14. }
  15. }
  16. }//end
  17. int main() {
  18. std::list<std::thread> tlist;
  19. for (int i = 0; i < 3; i++) {
  20. tlist.push_back(std::thread(sellTicket,i));
  21. }
  22. for (std::thread & t : tlist) {
  23. t.join();
  24. }
  25. system("pause");
  26. return 0;
  27. }

上面的图片中我们知道lock_gurad 的拷贝构造函数被关闭了,所以当我们遇到函数调用需要拷贝构造lock_guard的时候,就有障碍了,这个时候可以用unique_lock

unique_lock 转移指针,支持带右值得拷贝赋值,支持参数传递拷贝构造的,他的左值的拷贝构造也是被关闭了 看下图

原文链接:https://www.cnblogs.com/erichome/p/16976013.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号