std::thread和std::this_thread的详细说明-程序员宅基地

技术标签: c++  Powered by 金山文档  C++高级编程  

<thread>头文件包含了std::thread类和std::this_thread命名空间的声明。C++开发中include <thread>头文件,就可以使用std:thread线程类和std::this_thread命名空间,std::this_thread这个命名空间包含了对当前线程的一些基本操作,如获取当前线程id、休眠当前线程、让渡当前线程的时间片给其他线程等。

一、std::thread类

std::thread类来表示执行的各个线程。

执行线程是实际上是执行一系列指令,可以在多线程环境中与其他此类序列同时执行,同时共享相同的地址空间。

一个初始化的线程(std::thread)对象表示活动的执行线程,即初始化后std::thread立即运行;这样的线程对象是可连接的(joinable),并且具有唯一的线程id。

默认构造的(未初始化的)线程对象是不可连接的(not joinable),其线程id对于所有不可连接线程都是通用的。

如果move线程,或者对它们调用join或detach,则可连接线程将变得不可连接。

(1)thread成员变量:

id

Thread id (public member type)

native_handle_type

Native handle type (public member type)

(2)thread成员函数:

(constructor)

Construct thread (public member function)

(destructor)

Thread destructor (public member function)

operator=

Move-assign thread (public member function)

get_id

Get thread id (public member function)

joinable

Check if joinable (public member function)

join

Join thread (public member function)

detach

Detach thread (public member function)

swap

Swap threads (public member function)

native_handle

Get native handle (public member function)

hardware_concurrency [static]

Detect hardware concurrency (public static member function)

以下为thread主要的成员函数使用介绍。

1、joinable(判断线程是否可连接)

bool joinable() const noexcept;

检查线程是否可连接,返回线程对象是否可连接。

(1)如果线程对象表示执行线程,则它是可连接的。

(2)在以下任何情况下,线程对象都不可连接:

  • 如果它是默认构造的。

  • 如果它已被move(构造另一个线程对象,或分配给另一个线程)。

  • 如果已调用其成员join或detach。

2、join(连接线程,阻塞调用线程)

void join();

连接(join)线程,当线程执行完成时,函数返回。

join()函数能够保证调用线程和被调用线程同步,join()函数将阻塞调用该join()函数线程的执行,直到被调用线程的函数返回。调用join()函数后,线程对象变得不可连接,可以安全销毁。

3、detach(分离线程,调用线程和被调用线程各自独立运行)

void detach();

分离(detach)线程将对象表示的线程与调用线程分离,允许它们彼此独立地执行。

这两个线程都继续运行,不会以任何方式阻塞或同步。请注意,当其中一方结束执行时,其资源将被释放。调用此函数后,线程对象变得不可连接,可以安全销毁。

4、swap(交换线程)

void swap (thread& x) noexcept;

交换线程,将对象的状态与x的状态交换。

swap函数与thread的移动构造函数和移动赋值函数作用一样。

thread::thread

Constructthread (public member function)

thread::operator=

Move-assignthread (public member function)

5、thread构造函数

default (1)

thread() noexcept;

initialization (2)

template <class Fn, class... Args>explicit thread (Fn&& fn, Args&&... args);

copy [deleted] (3)

thread (const thread&) = delete;

move (4)

thread (thread&& x) noexcept;

由以上可知,拷贝构造函数已经delete,构造函数中只有三种构造函数可用:

(1) 默认构造函数

构造一个不表示任何执行线程的线程对象。

(2) 初始化构造函数

构造一个线程对象,该对象表示新的可连接执行线程。

新的执行线程调用fn函数传递args 作为参数。

此构造的完成与fn函数的调用开始同步。

(3) 移动构造函数

构造一个线程对象,该对象获取由x表示的执行线程(如果有)。此操作不会以任何方式影响已移动线程的执行,它只是传输其处理程序。之后x对象不再表示任何执行线程。

6、thread赋值函数

move (1)

thread& operator= (thread&& rhs) noexcept;

copy [deleted] (2)

thread& operator= (const thread&) = delete;

Thread赋值函数的拷贝赋值函数已经delete,只有移动赋值函数可用,参数为右值thread,也叫移动分配线程函数。

如果对象当前不可连接,它将获取由rhs表示的执行线程(如果有的话)。

如果它是可连接的,则调用terminate()。

在调用之后,rhs不再表示任何执行线程(就像默认构造的一样)。

7、thread的应用示例1:join()用法

// thread example
#include <iostream>       // std::cout
#include <thread>         // std::thread
 
void foo() 
{
  // do stuff...
}

void bar(int x)
{
  // do stuff...
}

int main() 
{
  std::thread first (foo);     // spawn new thread that calls foo()
  std::thread second (bar,0);  // spawn new thread that calls bar(0)

  std::cout << "main, foo and bar now execute concurrently...\n";

  // synchronize threads:
  first.join();                // pauses until first finishes
  second.join();               // pauses until second finishes

  std::cout << "foo and bar completed.\n";

  return 0;
}

输出:

main, foo and bar now execute concurrently...

foo and bar completed.

8、thread的应用示例2:detach()用法

#include <iostream>       // std::cout
#include <thread>         // std::thread, std::this_thread::sleep_for
#include <chrono>         // std::chrono::seconds
 
void pause_thread(int n) 
{
  std::this_thread::sleep_for (std::chrono::seconds(n));
  std::cout << "pause of " << n << " seconds ended\n";
}
 
int main() 
{
  std::cout << "Spawning and detaching 3 threads...\n";
  std::thread (pause_thread,1).detach();
  std::thread (pause_thread,2).detach();
  std::thread (pause_thread,3).detach();
  std::cout << "Done spawning threads.\n";

  std::cout << "(the main thread will now pause for 5 seconds)\n";
  // give the detached threads time to finish (but not guaranteed!):
  pause_thread(5);
  return 0;
}

输出(5秒后):

Spawning and detaching 3 threads...

Done spawning threads.

(the main thread will now pause for 5 seconds)

pause of 1 seconds ended

pause of 2 seconds ended

pause of 3 seconds ended

pause of 5 seconds ended

9、thread的应用示例2:移动赋值函数(=)用法

// example for thread::operator=
#include <iostream>       // std::cout
#include <thread>         // std::thread, std::this_thread::sleep_for
#include <chrono>         // std::chrono::seconds
 
void pause_thread(int n) 
{
  std::this_thread::sleep_for (std::chrono::seconds(n));
  std::cout << "pause of " << n << " seconds ended\n";
}

int main() 
{
  std::thread threads[5];                         // default-constructed threads

  std::cout << "Spawning 5 threads...\n";
  for (int i=0; i<5; ++i)
    threads[i] = std::thread(pause_thread,i+1);   // move-assign threads

  std::cout << "Done spawning threads. Now waiting for them to join:\n";
  for (int i=0; i<5; ++i)
    threads[i].join();

  std::cout << "All threads joined!\n";

  return 0;
}

输出(5秒后):

Spawning 5 threads...

Done spawning threads. Now waiting for them to join:

pause of 1 seconds ended

pause of 2 seconds ended

pause of 3 seconds ended

pause of 4 seconds ended

pause of 5 seconds ended

All threads joined!

二、std::this_thread命名空间

此命名空间提供了访问当前线程的一组函数。

1、this_thread命名空间的函数介绍

get_id

获得当前线程id

yield

将当前线程时间片让渡给其他线程

sleep_until

当前线程休眠直到某个时间点

sleep_for

当前线程休眠一段时间

2、this_thread命名空间的示例:当前线程休眠

// this_thread::sleep_for example
#include <iostream>       // std::cout, std::endl
#include <thread>         // std::this_thread::sleep_for
#include <chrono>         // std::chrono::seconds
 
int main() 
{
  std::cout << "countdown:\n";
  for (int i=10; i>0; --i) {
    std::cout << i << std::endl;
    std::this_thread::sleep_for (std::chrono::seconds(1));
  }
  std::cout << "Lift off!\n";

  return 0;
}

输出(10秒后):

countdown:

10

9

8

7

6

5

4

3

2

1

Lift off!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_43369786/article/details/129469335

智能推荐

敏捷开发(scrum)简介-程序员宅基地

文章浏览阅读7.7k次,点赞6次,收藏61次。敏捷开发(scrum)是一种软件开发的流程,强调快速反应、快速迭代、价值驱动。Scrum的英文意思是橄榄球运动的一个专业术语,表示“争球”的动作;运用该流程,你就能看到你团队高效的工作。一、四大价值观(特点)敏捷开发的特点就是下面4句话:「个体与交互」胜过「过程与工具」「可以工作的软件」胜过「面面俱到的文挡」「客户协作」胜过「合同谈判」「响应变化」胜过「遵循计划」说明:(1)敏捷开发(scrum)适用于竞争激烈,快速变化的市场。 敏捷的客户协作观念,快速迭代能帮助团队以最小成本,最快速_敏捷开发

string.h头文件和strings.h的区别-程序员宅基地

文章浏览阅读3.5k次。首先我们看一下man string 里面的内容:可见,strings 头文件中包含了部分函数,没有在 string.h 中出现的。上图的环境是 macOS Sierra 版本号为:10.12.6包括; index, rindex, strcasecmp, strncasecmp 这四个函数。为了一探这个头文件是不是只有macos 这种 Unix-like 系统中才出现。我在Linu..._strings.h

一、Jquery入门(超详)-程序员宅基地

文章浏览阅读4.3k次,点赞21次,收藏48次。本文将带领大家了解 jQuery 的定义,它有什么作用,我们为什么要学它,以及如何使用它,它的语法是什么,最后对比了 jQuery 对象和 DOM 对象的区别。_jquery

【SassError: expected selector报错 用::v-deep 替换 /deep/的真实写法】_unexpected unknown pseudo-element selector "::v-de-程序员宅基地

文章浏览阅读2.7k次,点赞2次,收藏2次。关于SassError: expected selector报错 ::v-deep 替换 /deep/的正确替换方式_unexpected unknown pseudo-element selector "::v-deep

Linux学习笔记 第0章:计算机概论_字长 位宽-程序员宅基地

文章浏览阅读301次。0.1.0计算机本质计算机:接受用户输入的命令与数据,经由中央处理器的算术与逻辑单元运算处理后产生储存成有用的信息算术逻辑单元(Arithmetic&logical Unit:是中央处理器(CPU)的执行单元,是所有中央处理器的核心组成部分,由与门 和或门构成的算术逻辑单元,主要功能是进行二位元的算术运算,如加减乘(不包括整数除法)。基本上,在所有现代CPU体系结构中,二进制都以补码的..._字长 位宽

Curve25519 Field域2^255-19内的快速运算_curve25519标量乘-程序员宅基地

文章浏览阅读1.2k次,点赞3次,收藏3次。1. 引言对于Curve25519,其Field域内的module Fp = 2255-19。若采用常规的Montgomery reduce算法,其运算性能并不是最优的。如要求某整数 u mod (2^255-19),可将m整数用多项式做如下表示:u=∑iuixi,其中,ui=n∗2⌈25.5i⌉,n∈Nu=\sum_{i}^{}u_ix^i,其中,u_i=n*2^{\left \lce..._curve25519标量乘

随便推点

Qt 22 布局管理器1 - QLayout,QBoxLayout,布局管理器的相互嵌套_qt layout可以嵌套layout吗-程序员宅基地

文章浏览阅读464次。布局管理器提供相关的类对界面组件进行布局管理能够自动排布窗口中的界面组件窗口变化后自动更新界面组件的大小QLayoutQLayout 是Qt 中布局管理器的抽象基类通过继承QLayout实现了功能各异且互补的布局管理器Qt中可以根据需要自定义布局管理器布局管理器不是界面部件,而是界面部件的定位策略QBoxLayout 布局管理器以水平或者垂直的方式管理界面组件水平:QHBoxLayout 水平布局管理器垂直:QVBoxLayout 垂直布局管理器sizePolicy:QSize_qt layout可以嵌套layout吗

error MSB6006 rc exe 已退出,代码为 5_vs2010报警 error msb6006: “rc.exe”已退出,代码为 5。-程序员宅基地

文章浏览阅读2.6k次。error MSB6006 rc exe 已退出,代码为 5_vs2010报警 error msb6006: “rc.exe”已退出,代码为 5。

如何用NAS打造私有协同办公系统?-程序员宅基地

文章浏览阅读6.2k次。对于人数不多的小型初创企业、工作室、SOHO人群来说,能够拥有自有的协同办公系统无疑是提高工作效率的好方法,同时将文件放在自己的服务器中,显然会更加安心,不用担心重要内容的泄露问题。因此,大家有没有这样想过,自己动手搭一套私有的、云端化的协同办公系统,搞定文件异地同步的同时,实现云端化的办公软件,并提升数据安全性。理想虽好,不过要亲手搞定这样的协同办公系统一定很困难吧?如果你真这样

假设你们的社团要精选社长,有两名候选人分别是A和B,社团每名同学必须并且只能投一票,最终的票多的人为社长。-程序员宅基地

文章浏览阅读33次。输出描述:一行,一个字符,A或B或E,输出A表示A得票数多,输出B表示B得票数多,输出E表示二人得票数相等。输入描述:一行,字符序列,包含A或B,输入以字符0结束。

BeanFactory和ApplicationContext有什么区别?_beanfactory和applicationcontext是干什么的-程序员宅基地

文章浏览阅读2.2k次,点赞2次,收藏2次。BeanFactory和ApplicationContext有什么区别? BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。其中ApplicationContext是BeanFactory的子接口。(1)BeanFactory:是Spring里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理..._beanfactory和applicationcontext是干什么的

java 项目管理 maven2.0学习笔记 _apt fml fr-程序员宅基地

文章浏览阅读4.5k次。转贴:http://blog.csdn.net/shiqiang1234/archive/2006/10/12/1331725.aspxMaven简介Maven最初的目的是在Jakarta Turbine项目中使构建处理简单化。几个项目之间使用到的Ant build文件差异很小,各个JAR都存入CVS。因此希望有一个标准的方法构建各个工程,清晰的定义一个工程的组成,一个容易的方法去发布项目_apt fml fr