c++ std::lock_guard在异常处理中死锁

nmpmafwu  于 2024-01-09  发布在  其他
关注(0)|答案(2)|浏览(257)

我在一个文档中读到std::lock_guard会在死锁中产生一个问题。我想知道处理这种情况的最佳实践是什么?
当在多个地方使用std::lock_guard处理异常时,会触发死锁
另外,分享更多的死锁例子也很好,这样我就可以避免将来的死锁。
我的代码

  1. #include <boost/asio.hpp>
  2. // // #include <boost/thread.hpp>
  3. #include <boost/bind/bind.hpp>
  4. #include <memory>
  5. #include <mutex>
  6. #include <iostream>
  7. #include <thread>
  8. #include <chrono>
  9. std::mutex global_stream_lock;
  10. void worker_thread(std::shared_ptr<boost::asio::io_service> iosvc, int i ){
  11. {
  12. std::lock_guard l {global_stream_lock};
  13. std::cout<<"Thread"<<i<<"started"<<std::endl;
  14. }
  15. try{
  16. std::lock_guard l {global_stream_lock};
  17. iosvc->run();
  18. std::cout<<"Thread "<<i<<"End \n";
  19. }
  20. catch(std::exception &ex){
  21. {
  22. std::cout << "Message: " << ex.what() << ".\n";
  23. }
  24. }
  25. }
  26. void throw_an_exception(std::shared_ptr<boost::asio::io_service> io_svc, int counter)
  27. {
  28. {
  29. std::lock_guard l {global_stream_lock};
  30. std::cout << "Throw Exception " << counter << "\n" ;
  31. }
  32. throw(std::runtime_error("The Exception !!!"));
  33. }
  34. int main(void) {
  35. std::shared_ptr<boost::asio::io_service> io_svc (new boost::asio::io_service);
  36. std::shared_ptr<boost::asio::io_service::work> worker (new boost::asio::io_service::work(*io_svc));
  37. std::vector<std::jthread> threads;
  38. {
  39. std::lock_guard l {global_stream_lock};
  40. std::cout << "The program will exit once all work has finished.\n";
  41. }
  42. boost::asio::io_service::strand strand(*io_svc);
  43. //boost::thread_group threads;
  44. for (int i =1; i<=3;++i)
  45. {
  46. threads.push_back(std::jthread{&worker_thread, io_svc, i});
  47. }
  48. // std::chrono::milliseconds sleep_times {1000};
  49. // std::this_thread::sleep_for(sleep_times);
  50. io_svc->post(boost::bind(&throw_an_exception, io_svc, 1));
  51. io_svc->post(boost::bind(&throw_an_exception, io_svc, 2));
  52. io_svc->post(boost::bind(&throw_an_exception, io_svc, 3));
  53. io_svc->post(boost::bind(&throw_an_exception, io_svc, 4));
  54. io_svc->post(boost::bind(&throw_an_exception, io_svc, 5));
  55. return 0;
  56. }

字符串
输出

  1. The program will exit once all work has finished.
  2. Thread1started


我认为死锁的发生是因为我在多个地方添加了std::lock_guard
如果我在下面的代码中删除锁保护,将不会有死锁,但只是想知道使用std::lock_guard的最佳解决方案是什么?

  1. void throw_an_exception(std::shared_ptr<boost::asio::io_service> io_svc, int counter)
  2. {
  3. {
  4. //commment below will addredd deadlock issue
  5. //std::lock_guard l {global_stream_lock};
  6. std::cout << "Throw Exception " << counter << "\n" ;
  7. }
  8. throw(std::runtime_error("The Exception !!!"));
  9. }

blmhpbnm

blmhpbnm1#

我找到解决办法了。
lock_guard应该只用于一个目的。显然上面是一个bug

  1. try {
  2. std::lock_guard l {global_stream_lock};
  3. iosvc->run();
  4. std::cout << "Thread "<<i<<"End \n";
  5. } catch(std::exception &ex) {
  6. {
  7. std::cout << "Message: " << ex.what() << ".\n";
  8. }
  9. }

字符串
变更为:

  1. try {
  2. iosvc->run();
  3. {
  4. std::lock_guard l {global_stream_lock};
  5. std::cout<<"Thread "<<i<<"End \n";
  6. }
  7. } catch(std::exception &ex) {
  8. {
  9. std::lock_guard l {global_stream_lock};
  10. std::cout << "Message: " << ex.what() << ".\n";
  11. }
  12. }


text book中的变量global_stream_lock应该只用于cout。
但如果有人能帮我解释一下我会很感激的。
当我在lock_guard作用域中包含**iosvc->run();**时,死锁是如何触发的?

展开查看全部
9vw9lbht

9vw9lbht2#

std::mutex global_stream_lock;替换为std::recursive_mutex global_stream_lock;

相关问题