std::thread和std::this_thread的详细说明

头文件包含了std::thread类和std::this_thread命名空间的声明。C++开发中include 头文件,就可以使用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 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        // std::cout
#include          // 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        // std::cout
#include          // std::thread, std::this_thread::sleep_for
#include          // 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        // std::cout
#include          // std::thread, std::this_thread::sleep_for
#include          // 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        // std::cout, std::endl
#include          // std::this_thread::sleep_for
#include          // 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!

你可能感兴趣的:(C++高级编程,c++)