• c++ 11 线程支持库 thread


    定义于头文件

    线程使得程序能在数个处理器核心同时执行。

    std::thread

    thread 表示单个执行线程。线程允许多个函数同时执行。

    线程在构造关联的线程对象时立即开始执行(等待任何OS调度延迟),从提供给作为构造函数参数的顶层函数开始。顶层函数的返回值将被忽略,而且若它以抛异常终止,则调用 std::terminate 。顶层函数可以通过 std::promise 或通过修改共享变量(可能需要同步,见 std::mutex 与 std::atomic )将其返回值或异常传递给调用方。

    std::thread 对象也可能处于不表示任何线程的状态(默认构造、被移动、 detach 或 join 后),并且执行线程可能与任何 thread 对象无关( detach 后)。

    没有两个 std::thread 对象会表示同一执行线程; std::thread 不是可复制构造 (CopyConstructible) 或可复制赋值 (CopyAssignable) 的,尽管它可移动构造 (MoveConstructible) 且可移动赋值 (MoveAssignable) 。

    构造函数

    1. thread() noexcept; (1) (C++11 起)
    2. thread( thread&& other ) noexcept;(2) (C++11 起)
    3. template< class Function, class... Args >
    4. explicit thread( Function&& f, Args&&... args ); (3) (C++11 起)
    5. thread(const thread&) = delete; (4) (C++11 起)

    构造新的 thread 对象。

    1) 构造不表示线程的新 thread 对象。

    2) 移动构造函数。构造表示曾为 other 所表示的执行线程的 thread 对象。此调用后 other 不再表示执行线程。

    3) 构造新的 std::thread 对象并将它与执行线程关联。新的执行线程开始执行

    std::invoke(decay_copy(std::forward(f)), 
                decay_copy(std::forward(args))...);

    其中 decay_copy 定义为

    template 
    std::decay_t decay_copy(T&& v) { return std::forward(v); }

    除了 decay_copy 的调用在调用方语境求值,故而任何求值和复制/移动参数中抛出的异常被抛到当前线程,而不用开始新线程。

    构造函数的调用完成同步于(定义于 std::memory_order )新的执行线程上 f 副本的调用开始。

    若 std::decay_t 是与 std::thread 相同的类型,则此构造函数不参与重载决议。

    (C++14 起)

    4) 复制构造函数被删除; thread 不可复制。没有二个 std::thread 对象可表示同一执行线程。

    参数

    other-用以构造此 thread 的另一 thread 对象
    f-执行于新线程的可调用 (Callable)
    args...-传递给新函数的参数

    后置条件

    1) get_id() 等于 std::thread::id() (即 joinable 为 false )

    2) other.get_id() 等于 std::thread::id() 而 get_id() 返回构造开始前 other.get_id() 的值

    3) get_id() 不等于 std::thread::id() (即 joinable 为 true )

    异常

    3) 若不能开始线程则抛出 std::system_error 。异常可能表示错误条件 std::errc::resource_unavailable_try_again 或另一实现限定的错误条件。

    注意

    到线程函数的参数被移动或按值复制。若需要传递引用参数给线程函数,则必须包装它(例如用 std::ref 或 std::cref )。

    忽略来自函数的任何返回值。若函数抛异常,则调用 std::terminate 。为将返回值或异常传递回调用方线程,可使用 std::promise 或 std::async 。

    调用示例

    1. #include
    2. #include
    3. using namespace std;
    4. void f1(int n)
    5. {
    6. for (int i = 0; i < 5; ++i)
    7. {
    8. std::cout << "Thread 1 executing, threadid: " << std::this_thread::get_id();
    9. std::cout << ", n: " << n << std::endl;
    10. ++n;
    11. std::this_thread::sleep_for(std::chrono::milliseconds(10));
    12. }
    13. }
    14. void f2(int& n)
    15. {
    16. for (int i = 0; i < 5; ++i)
    17. {
    18. std::cout << "Thread 2 executing, threadid: " << std::this_thread::get_id();
    19. std::cout << ", n: " << n << std::endl;
    20. ++n;
    21. std::this_thread::sleep_for(std::chrono::milliseconds(10));
    22. }
    23. }
    24. class foo
    25. {
    26. public:
    27. void bar()
    28. {
    29. for (int i = 0; i < 5; ++i)
    30. {
    31. std::cout << "Thread 3 executing, threadid: "
    32. << std::this_thread::get_id() << std::endl;
    33. ++n;
    34. std::this_thread::sleep_for(std::chrono::milliseconds(10));
    35. }
    36. }
    37. int n = 0;
    38. };
    39. class baz
    40. {
    41. public:
    42. void operator()()
    43. {
    44. for (int i = 0; i < 5; ++i)
    45. {
    46. std::cout << "Thread 4 executing, threadid: "
    47. << std::this_thread::get_id() << std::endl;
    48. ++n;
    49. std::this_thread::sleep_for(std::chrono::milliseconds(10));
    50. }
    51. }
    52. int n = 0;
    53. };
    54. int main()
    55. {
    56. int n = 0;
    57. foo f;
    58. baz b;
    59. std::thread t1; // t1 不是线程
    60. // std::thread t2(f1, n + 1);// 按值传递
    61. std::thread t3(f2, std::ref(n)); // 按引用传递
    62. std::thread t4(std::move(t3)); // t4 现在运行 f2() 。 t3 不再是线程
    63. // std::thread t5(&foo::bar, &f); // t5 在对象 f 上运行 foo::bar()
    64. // std::thread t6(b); // t6 在对象 b 上运行 baz::operator()
    65. // t2.join();
    66. t3.join();
    67. t4.join();
    68. // t5.join();
    69. // t6.join();
    70. return 0;
    71. }

    检查线程是否可合并,即潜在地运行于平行环境中

    std::thread::joinable
    bool joinable() const noexcept;             (C++11 起) 

    检查 thread 对象是否标识活跃的执行线程。具体是返回 true if get_id() != std::thread::id() 。故默认构造的 thread 不可合并。

    完成执行代码,但未被合并的线程仍被认为是活跃线程,从而可合并。

    参数

    (无)

    返回值

    若 thread 对象标识活跃的执行线程则为 true ,否则为 false

    返回线程的 id

    std::thread::get_id
    std::thread::id get_id() const noexcept;             (C++11 起) 

    返回标识与 *this 关联的线程的 std::thread::id 类型值。

    参数

    (无)

    返回值

    标识与 *this 关联的线程的 std::thread::id 类型值。若无关联的线程,则返回默认构造的 std::thread::id 。

    返回底层实现定义的线程句柄

    std::thread::native_handle
    native_handle_type native_handle();        (C++11 起) 

    返回实现定义的底层线程句柄。

    参数

    (无)

    返回值

    表示线程的实现定义句柄类型。

    异常

    (无)

    返回实现支持的并发线程数

    std::thread::hardware_concurrency
    static unsigned int hardware_concurrency() noexcept;         (C++11 起) 

    返回实现所支持的并发线程数。应该只把值当做提示。

    参数

    (无)

    返回值

    支持的并发线程数。若值非良定义或不可计算,则返回 ​0​ 。

    调用示例

    1. unsigned int n = std::thread::hardware_concurrency();
    2. std::cout << n << " concurrent threads are supported.\n";

    等待线程完成其执行

    std::thread::join
    void join();            (C++11 起) 

    阻塞当前线程,直至 *this 所标识的线程完成其执行。

    *this 所标识的线程的完成同步于join() 的成功返回。

    参数

    (无)

    返回值

    (无)

    后置条件

    joinable 为 false

    异常

    若错误发生则为 std::system_error 。

    错误条件

    • 若 this->get_id() == std::this_thread::get_id() (检测到死锁)则为 resource_deadlock_would_occur
    • 若线程非法则为 no_such_process
    • 若 joinable 为 false 则为 invalid_argument

    容许线程从线程句柄独立开来执行

    std::thread::detach
    void detach();         (C++11 起) 

    从 thread 对象分离执行的线程,允许独立地继续执行。一旦线程退出,则释放所有分配的资源。

    调用 detach 后, *this 不再占有任何线程。

    参数

    (无)

    返回值

    (无)

    后置条件

    joinable 为 false

    异常

    若 joinable() == false 或错误发生时为 std::system_error 。

    交换二个 thread 对象

    std::thread::swap
    void swap( thread& other ) noexcept;         (C++11 起) 

    互换二个 thread 对象的底层句柄。

    参数

    other-要与之交换的 thread

    返回值

    (无)

  • 相关阅读:
    indiegogo众筹代理经验分享
    神经网络和深度神经网络,深度神经网络发展历程
    清华训练营悟道篇之操作系统的调用接口
    学习Opencv(蝴蝶书/C++)相关——1. 前言 和 第1章.概述
    考研数据结构与算法(八)查找
    单商户社区团购系统小程序源码
    【高等数学基础进阶】不定积分-part2
    HBase Meta 元信息表修复实践
    连续十日票房日冠,《人生大事》带热了电影大盘!它凭何突出重围?
    环境生态学知识点
  • 原文地址:https://blog.csdn.net/qq_40788199/article/details/126070502