本文转载自:https://github.com/forhappy/Cplusplus-Concurrency-In-Practice/blob/master/zh/chapter3-Thread/Introduction-to-Thread.md

本节将详细介绍 std::thread 的用法。

std::thread 在 <thread> 头文件中声明,因此使用 std::thread 需包含 <thread> 头文件。

<thread> 头文件摘要

<thread> 头文件声明了 std::thread 线程类及 std::swap (交换两个线程对象)辅助函数。另外命名空间 std::this_thread 也声明在 <thread> 头文件中。下面是 C++11 标准所定义的 <thread> 头文件摘要:

参见 N3242=11-0012 草案第 30.3 节 Threads(p1133)。

namespace std {#define __STDCPP_THREADS__ __cplusplusclass thread;void swap(thread& x, thread& y);namespace this_thread {thread::id get_id();void yield();template <class Clock, class Duration>void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);template <class Rep, class Period>void sleep_for(const chrono::duration<Rep, Period>& rel_time);}
}

<thread> 头文件主要声明了 std::thread 类,另外在 std::this_thread 命名空间中声明了 get_idyieldsleep_until 以及 sleep_for 等辅助函数,本章稍微会详细介绍 std::thread 类及相关函数。

std::thread 类摘要

std::thread 代表了一个线程对象,C++11 标准声明如下:

namespace std {class thread {public:// 类型声明:class id;typedef implementation-defined native_handle_type;// 构造函数、拷贝构造函数和析构函数声明:thread() noexcept;template <class F, class ...Args> explicit thread(F&& f, Args&&... args);~thread();thread(const thread&) = delete;thread(thread&&) noexcept;thread& operator=(const thread&) = delete;thread& operator=(thread&&) noexcept;// 成员函数声明:void swap(thread&) noexcept;bool joinable() const noexcept;void join();void detach();id get_id() const noexcept;native_handle_type native_handle();// 静态成员函数声明:static unsigned hardware_concurrency() noexcept;};
}

std::thread 中主要声明三类函数:(1). 构造函数、拷贝构造函数及析构函数;(2). 成员函数;(3). 静态成员函数。另外, std::thread::id 表示线程 ID,同时 C++11 声明如下:

namespace std {class thread::id {public:id() noexcept;};bool operator==(thread::id x, thread::id y) noexcept;bool operator!=(thread::id x, thread::id y) noexcept;bool operator<(thread::id x, thread::id y) noexcept;bool operator<=(thread::id x, thread::id y) noexcept;bool operator>(thread::id x, thread::id y) noexcept;bool operator>=(thread::id x, thread::id y) noexcept;template<class charT, class traits>basic_ostream<charT, traits>&operator<< (basic_ostream<charT, traits>& out, thread::id id);// Hash 支持template <class T> struct hash;template <> struct hash<thread::id>;
}

std::thread 详解

std::thread 构造和赋值

std::thread 构造函数

默认构造函数 (1) thread() noexcept;
初始化构造函数 (2) template <class Fn, class... Args>
explicit thread(Fn&& fn, Args&&... args);
拷贝构造函数 [deleted] (3) thread(const thread&) = delete;
Move 构造函数 (4) thread(thread&& x) noexcept;
  1. 默认构造函数(1),创建一个空的 std::thread 执行对象。
  2. 初始化构造函数(2),创建一个 std::thread 对象,该 std::thread 对象可被 joinable,新产生的线程会调用 fn 函数,该函数的参数由 args 给出。
  3. 拷贝构造函数(被禁用)(3),意味着 std::thread 对象不可拷贝构造。
  4. Move 构造函数(4),move 构造函数(move 语义是 C++11 新出现的概念,详见附录),调用成功之后 x 不代表任何 std::thread 执行对象。

注意:可被 joinable 的 std::thread 对象必须在他们销毁之前被主线程 join 或者将其设置为 detached.

std::thread 各种构造函数例子如下(参考):

#include <iostream>
#include <utility>
#include <thread>
#include <chrono>
#include <functional>
#include <atomic>void f1(int n)
{for (int i = 0; i < 5; ++i) {std::cout << "Thread " << n << " executing\n";std::this_thread::sleep_for(std::chrono::milliseconds(10));}
}void f2(int& n)
{for (int i = 0; i < 5; ++i) {std::cout << "Thread 2 executing\n";++n;std::this_thread::sleep_for(std::chrono::milliseconds(10));}
}int main()
{int n = 0;std::thread t1; // t1 is not a threadstd::thread t2(f1, n + 1); // pass by valuestd::thread t3(f2, std::ref(n)); // pass by referencestd::thread t4(std::move(t3)); // t4 is now running f2(). t3 is no longer a threadt2.join();t4.join();std::cout << "Final value of n is " << n << '\n';
}

std::thread 赋值操作

Move 赋值操作 (1) thread& operator=(thread&& rhs) noexcept;
拷贝赋值操作 [deleted] (2) thread& operator=(const thread&) = delete;
  1. Move 赋值操作(1),如果当前对象不可 joinable,需要传递一个右值引用(rhs)给 move 赋值操作;如果当前对象可被 joinable,则会调用 terminate() 报错。
  2. 拷贝赋值操作(2),被禁用,因此 std::thread 对象不可拷贝赋值。

请看下面的例子:

#include <stdio.h>
#include <stdlib.h>#include <chrono>    // std::chrono::seconds
#include <iostream>  // std::cout
#include <thread>    // std::thread, std::this_thread::sleep_forvoid thread_task(int n) {std::this_thread::sleep_for(std::chrono::seconds(n));std::cout << "hello thread "<< std::this_thread::get_id()<< " paused " << n << " seconds" << std::endl;
}int main(int argc, const char *argv[])
{std::thread threads[5];std::cout << "Spawning 5 threads...\n";for (int i = 0; i < 5; i++) {threads[i] = std::thread(thread_task, i + 1);}std::cout << "Done spawning threads! Now wait for them to join\n";for (auto& t: threads) {t.join();}std::cout << "All threads joined.\n";return EXIT_SUCCESS;
}

其他成员函数

本小节例子来自 http://en.cppreference.com

  • get_id: 获取线程 ID,返回一个类型为 std::thread::id 的对象。请看下面例子:

      #include <iostream>#include <thread>#include <chrono>void foo(){std::this_thread::sleep_for(std::chrono::seconds(1));}int main(){std::thread t1(foo);std::thread::id t1_id = t1.get_id();std::thread t2(foo);std::thread::id t2_id = t2.get_id();std::cout << "t1's id: " << t1_id << '\n';std::cout << "t2's id: " << t2_id << '\n';t1.join();t2.join();}
    
  • joinable: 检查线程是否可被 join。检查当前的线程对象是否表示了一个活动的执行线程,由默认构造函数创建的线程是不能被 join 的。另外,如果某个线程 已经执行完任务,但是没有被 join 的话,该线程依然会被认为是一个活动的执行线程,因此也是可以被 join 的。

      #include <iostream>#include <thread>#include <chrono>void foo(){std::this_thread::sleep_for(std::chrono::seconds(1));}int main(){std::thread t;std::cout << "before starting, joinable: " << t.joinable() << '\n';t = std::thread(foo);std::cout << "after starting, joinable: " << t.joinable() << '\n';t.join();}
    
  • join: Join 线程,调用该函数会阻塞当前线程,直到由 *this 所标示的线程执行完毕 join 才返回。

      #include <iostream>#include <thread>#include <chrono>void foo(){// simulate expensive operationstd::this_thread::sleep_for(std::chrono::seconds(1));}void bar(){// simulate expensive operationstd::this_thread::sleep_for(std::chrono::seconds(1));}int main(){std::cout << "starting first helper...\n";std::thread helper1(foo);std::cout << "starting second helper...\n";std::thread helper2(bar);std::cout << "waiting for helpers to finish..." << std::endl;helper1.join();helper2.join();std::cout << "done!\n";}
    
  • detach: Detach 线程。 将当前线程对象所代表的执行实例与该线程对象分离,使得线程的执行可以单独进行。一旦线程执行完毕,它所分配的资源将会被释放。

调用 detach 函数之后:

  1. *this 不再代表任何的线程执行实例。
  2. joinable() == false
  3. get_id() == std:

    std::thread相关推荐

    1. C++11 新特性之std::thread

      C++11 新特性之std::thread 原文:https://blog.csdn.net/oyoung_2012/article/details/78958274 从C++11开始,C++标准库已 ...

    2. std thread

      不要用std::thread写裸线程 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/daan_112211/article/details/1908 ...

    3. 并发,std::thread

      2019独角兽企业重金招聘Python工程师标准>>> std::thread  定义一个线程对象,并管理关联的线程 备注: 你可以使用 thread 对象来观察和管理在应用程序中的 ...

    4. 【多线程】C++11进行多线程开发 (std::thread)

      文章目录 创建线程 std::thread 类 使用join() 使用 detach() 警惕作用域 线程不能复制 给线程传参 传递指针 传递引用 以类成员函数为线程函数 以容器存放线程对象 互斥量 ...

    5. C++11学习笔记-----线程库std::thread

      在以前,要想在C++程序中使用线程,需要调用操作系统提供的线程库,比如linux下的<pthread.h>.但毕竟是底层的C函数库,没有什么抽象封装可言,仅仅透露着一种简单,暴力美 C++ ...

    6. C++ std::thread 和 std::jthread 使用详解 (含C++20新特性)

      目录 std::thread std::thread 构造函数 观察器 操作 std::jthread std::jthread 构造函数 观察器 操作 停止记号处理 管理当前线程的函数 yield( ...

    7. std::jthread与std::thread的区别

      特性上,std::jthread相比std::thread主要增加了以下两个功能: 1.std::jthread对象被destruct时,会自动调用join,等待其所表示的执行流结束. 2.支持外部请 ...

    8. c++11仔细地将参数传递给线程std::thread

      要将参数传递给线程的可关联对象或函数,只需将参数传递给std::thread构造函数. 默认情况下,所有的参数都将复制到新线程的内部存储中. 看一个例子: 给线程传递单个参数 #include < ...

    9. std::thread 不 join

      std::thread 构造之后 使用 detach.就可以了

    10. C++11并发编程:多线程std::thread

      一:概述 C++11引入了thread类,大大降低了多线程使用的复杂度,原先使用多线程只能用系统的API,无法解决跨平台问题,一套代码平台移植,对应多线程代码也必须要修改.现在在C++11中只需使用语 ...

    最新文章

    1. C++模拟游戏中鼠标点击和键盘按键
    2. attribute 'groups' of type 'int' is not usable in a script method
    3. WP7 App性能优化(8):检测应用程序性能(Ⅰ)
    4. Boost.Test 断言的介绍
    5. 洛谷 P1754 球迷购票问题
    6. Flutter 之 StatefulWidget和StatelessWidget
    7. 使用Python检查密码安全程度
    8. 双目测距(四)--罗德里格斯变换
    9. 关于Eclipse的常用快捷键
    10. ai人工智能对话了_对话式AI:智能虚拟助手和未来之路。
    11. Python初学16——程序设计方法学
    12. 遗传算法适应度计算函数——ranking
    13. 2022edu教育邮箱哪个好?申请注册教育邮箱很难吗?
    14. 微软出了一个Python小白神器!
    15. 遍历读取文件夹下的所有文件
    16. R语言 | 利用tushare获取股票k线、市值、换手率,市盈率等指标
    17. 2015年职称计算机考试宝典,2015年度职称计算机考试宝典.doc
    18. 机器语言、汇编语言和高级语言之间的关系
    19. 如何开发一个基于 Vue 的 ui 组件库
    20. matlab thd 论坛,matlab如何仿真thd

    热门文章

    1. python填空题及答案知乎_zhihu-python
    2. mysql 自定义函数 找不到表,mysql判断表记录是否存在,不存在则插入新纪录
    3. springboot 初始化一个常量map_C++ 惯用法: const 常量和字面量
    4. dom控制html元素编号,JavaScript DOM对象控制HTML元素详解
    5. mysql 存储过程 锁表_MYSQL锁表问题的解决方法
    6. spring整合mybatis(详细)
    7. mysql_分组查询
    8. 泰拉瑞亚服务器存档位置,泰拉瑞亚国服存档怎么恢复 国服存档位置
    9. python 数组中取出最小值_每日算法系列【LeetCode 153】寻找旋转排序数组中的最小值...
    10. python读取csv内容变为nan,python – 获取pandas.read_csv以空字符串而不是nan读取空值...