• 使用 RAII 完成线程等待


    当使用 std::thread 对象执行线程时,必须要调用 join() (或者 detach(),由于 detach() 可以立即调用,所以这里只考虑 join())

     1 #include <iostream>
     2 #include <thread>
     3 #include <chrono>
     4 
     5 using namespace std;
     6 
     7 void threadInvoker()
     8 {
     9     cout << "thread begin
    ";
    10     this_thread::sleep_for(chrono::milliseconds(2000));
    11     cout << "thread end
    ";
    12 }
    13 
    14 void doSomething()
    15 {
    16     cout << "doSomething begin
    ";
    17     this_thread::sleep_for(chrono::milliseconds(4000));
    18     cout << "doSomething end
    ";
    19 }
    20 
    21 void doOther()
    22 {
    23 }
    24 
    25 void f()
    26 {
    27     thread t(threadInvoker);
    28 
    29     doSomething();
    30 
    31     doOther();
    32     t.join();
    33 }
    34 
    35 int main()
    36 {
    37     f();
    38 }

    编译:g++ -std=c++11 -pthread test.cpp

    如果 doSomething() 会产生异常,则尝试捕获

     1 #include <iostream>
     2 #include <thread>
     3 #include <chrono>
     4 
     5 using namespace std;
     6 
     7 void threadInvoker()
     8 {
     9     cout << "thread begin
    ";
    10     this_thread::sleep_for(chrono::milliseconds(2000));
    11     cout << "thread end
    ";
    12 }
    13 
    14 void doSomething()
    15 {
    16     cout << "doSomething begin
    ";
    17     this_thread::sleep_for(chrono::milliseconds(4000));
    18     throw 0;
    19     cout << "doSomething end
    ";
    20 }
    21 
    22 void doOther()
    23 {
    24 }
    25 
    26 void f()
    27 {
    28     thread t(threadInvoker);
    29 
    30     try {
    31         doSomething();
    32     }
    33     catch (...) {
    34         cout << "catch exception
    ";
    35         t.join();
    36         return;
    37     }
    38 
    39     doOther();
    40     t.join();
    41 }
    42 
    43 int main()
    44 {
    45     f();
    46 }

    但是必须在 catch 块里调用 t.join(),否则会 crash。如果条件一多,很可能会在某个分支下遗忘 t.join()。

    因此可以使用 RAII 来避免,在析构函数中进行 join()

     1 #include <iostream>
     2 #include <thread>
     3 #include <chrono>
     4 
     5 using namespace std;
     6 
     7 class ThreadGuard
     8 {
     9 public:
    10     explicit ThreadGuard(thread& t):mT(t) {}
    11     ~ThreadGuard()
    12     {
    13         if (mT.joinable()) {
    14             cout << "join
    ";
    15             mT.join();
    16         }
    17     }
    18     ThreadGuard(ThreadGuard const&) = delete;
    19     ThreadGuard& operator=(ThreadGuard const&) = delete;
    20 private:
    21     thread& mT;
    22 };
    23 
    24 void threadInvoker()
    25 {
    26     cout << "thread begin
    ";
    27     this_thread::sleep_for(chrono::milliseconds(2000));
    28     cout << "thread end
    ";
    29 }
    30 
    31 void doSomething()
    32 {
    33     cout << "doSomething begin
    ";
    34     this_thread::sleep_for(chrono::milliseconds(4000));
    35     throw 0;
    36     cout << "doSomething end
    ";
    37 }
    38 
    39 void doOther()
    40 {
    41 }
    42 
    43 void f()
    44 {
    45     thread t(threadInvoker);
    46     ThreadGuard tg(t);
    47 
    48     try {
    49         doSomething();
    50     }
    51     catch (...) {
    52         cout << "catch exception
    ";
    53         return;
    54     }
    55 
    56     doOther();
    57 }
    58 
    59 int main()
    60 {
    61     f();
    62 }

    利用局部对象的析构保证 join() 的调用

  • 相关阅读:
    解决安装mysql时出现的三种问题
    解决fences2.01在win8.1的状态下无法移动桌面图标问题
    利用Xshell5从本机上向Linux(虚拟机中)上传文件
    PHP加密解密函数(带有效期,过了有效期也解不了)
    js检查身份证号是否正确
    JS中事件绑定函数,事件捕获,事件冒泡
    js获取元素宽高、位置相关知识汇总
    JS中让新手倍感震惊、违反直觉、出乎意料、的一些知识点汇总记录
    Hbuilder工具使用
    HTML、CSS、JS中常用的东西在IE中兼容问题汇总
  • 原文地址:https://www.cnblogs.com/jingyg/p/5970003.html
Copyright © 2020-2023  润新知