C++11 线程类(Thread)学习笔记

文档声明:
以下资料均属于本人在学习过程中产出的学习笔记,如果错误或者遗漏之处,请多多指正。并且该文档在后期会随着学习的深入不断补充完善。


资料仅供学习交流使用。
作者:Aliven888

1、简述

Thread:表示执行线程的类。

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

初始化的线程对象表示活动的执行线程;这样的线程对象是可连接的,并且具有唯一的线程ID。

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

如果从中移出可连接线程,或者如果在它们上调用了join或detach,则该线程将不可连接。

2、接口描述

Member types

名称描述
id线程 id (public member type)
native_handle_type本机句柄类型 (public member type)

Member functions

名称描述
(constructor)构造函数 (public member function)
(destructor)析构函数 (public member function)
operator=Move-assign thread (public member function)
get_id获取线程 id (public member function)
joinable检查是否可加入 (public member function)
join加入线程 (public member function)
detach分离线程 (public member function)
swap交换两个线程 (public member function)
native_handle获取本机句柄类型 (public member function)
hardware_concurrency [static]检测硬件并发 (public static member function)

3、接口介绍

3.1、成员类型(Member types)

3.1.1、Thread::id

默认构造的thread :: id对象的值标识不可连接的线程,因此,其值等于任何此类线程的成员thread :: get_id返回的值。

对于可连接线程,thread :: get_id返回此类型的唯一值,该值与其他任何可连接或不可连接线程返回的值不相等。

请注意,某些库实现可能会重新利用无法再加入的终止线程的thread :: id值。

3.1.2、Thread::native_handle_type

如果库实现支持,则该成员类型仅出现在类线程中。

它是thread :: native_handle返回的类型,具有有关线程的特定于实现的信息。

3.2、成员函数(Member functions)

3.2.1、构造函数(Thread::Thread(…))

默认构造函数:

	Thread::thread() noexcept;

功能:构造一个不代表任何执行线程的线程对象。

初始化构造函数:

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

功能:构造一个代表新的可连接执行线程的线程对象。新的执行线程调用fn传递args作为参数(使用其左值或右值引用的衰减副本)。该构造函数的完成与该fn副本的调用开始同步。

复制构造函数

Thread::thread (const thread&) = delete;

功能:删除构造函数形式(线程对象无法复制)。

移动构造函数

	Thread::thread (thread&& x) noexcept;

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

构造函数参量介绍:
fn: 指向函数的指针,指向成员的指针或任何类型的可移动构造的函数对象(即,其类定义了operator()的对象,包括闭包和函数对象)。返回值(如果有)将被忽略。

args …: 传递给fn调用的参数(如果有)。它们的类型应是可移动构造的。如果fn是成员指针,则第一个参数应是为其定义了该成员的对象(或其引用或指向它的指针)。

X: 线程对象,其状态已移至构造对象。

注意: fn和args …是模板参数;如果隐式推导,则它们是将参数绑定到的正确的左值或右值引用类型。但是请注意,在新线程中对fn的调用中,始终使用fn和args …的衰减副本。

	std::atomic<int> global_counter (0);
	
	void increase_global (int n) { for (int i=0; i<n; ++i) ++global_counter; }
	
	void increase_reference (std::atomic<int>& variable, int n) { for (int i=0; i<n; ++i) ++variable; }
	
	struct C : std::atomic<int> {
	  C() : std::atomic<int>(0) {}
	  void increase_member (int n) { for (int i=0; i<n; ++i) fetch_add(1); }
	};
	
	int main ()
	{
	  std::vector<std::thread> threads;
	
	  std::cout << "increase global counter with 10 threads...\n";
	  for (int i=1; i<=10; ++i)
	    threads.push_back(std::thread(increase_global,1000));
	
	  std::cout << "increase counter (foo) with 10 threads using reference...\n";
	  std::atomic<int> foo(0);
	  for (int i=1; i<=10; ++i)
	    threads.push_back(std::thread(increase_reference,std::ref(foo),1000));
	
	  std::cout << "increase counter (bar) with 10 threads using member...\n";
	  
	  for (int i=1; i<=10; ++i)
	    threads.push_back(std::thread(&C::increase_member,std::ref(bar),1000));
	
	  std::cout << "synchronizing all threads...\n";
	  for (auto& th : threads) th.join();
	
	  std::cout << "global_counter: " << global_counter << '\n';
	  std::cout << "foo: " << foo << '\n';
	  std::cout << "bar: " << bar << '\n';
	
	  return 0;
	}

输出:
increase global counter using 10 threads...
increase counter (foo) with 10 threads using reference...
increase counter (bar) with 10 threads using member...
synchronizing all threads...
global_counter: 10000
foo: 10000
bar: 10000
3.2.2、析构函数(Thread::~Thread())
	Thread::~Thread()

线程析构函数,常用于销毁线程对象。如果线程在销毁时是可连接的,则调用terminate()。

3.2.2、运算符重载(Thread::operator=)

常用接口有:

	move (1)	
	thread& operator= (thread&& rhs) noexcept;
	
	copy [deleted] (2)	
	thread& operator= (const thread&) = delete;
	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;
	}

输出:
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!
3.2.4、获取线程ID(Thread::get_id())
	std::thread::id get_id() const noexcept;

功能: 获取线程ID

返回值: 如果线程对象是可连接的,则该函数返回一个唯一标识线程的值。如果线程对象不可连接,则该函数返回成员类型为thread :: id的默认构造的对象。

	std::thread::id main_thread_id = std::this_thread::get_id();
	
	void is_main_thread() {
	  if ( main_thread_id == std::this_thread::get_id() )
	    std::cout << "This is the main thread.\n";
	  else
	    std::cout << "This is not the main thread.\n";
	}
	
	int main() 
	{
	  is_main_thread();
	  std::thread th (is_main_thread);
	  th.join();
	}

输出:
This is the main thread.
This is not the main thread.
3.2.5、检查是否可加入(Thread::joinable())
	bool joinable() const noexcept;

功能: 检查是否可加入

返回值: 返回线程对象是否可连接。如果线程对象表示执行线程,则该对象是可连接的。如果线程可连接,则为true。否则为false。

注意事项:
在以下任何情况下,线程对象均不可连接:
如果它是默认构造的。
如果已将其移出(构造另一个线程对象或对其进行分配)。
是否已调用其成员join或detach。

	void mythread() 
	{
	  // do stuff...
	}
	 
	int main() 
	{
	  std::thread foo;
	  std::thread bar(mythread);
	
	  std::cout << "Joinable after construction:\n" << std::boolalpha;
	  std::cout << "foo: " << foo.joinable() << '\n';
	  std::cout << "bar: " << bar.joinable() << '\n';
	
	  if (foo.joinable()) foo.join();
	  if (bar.joinable()) bar.join();
	
	  std::cout << "Joinable after joining:\n" << std::boolalpha;
	  std::cout << "foo: " << foo.joinable() << '\n';
	  std::cout << "bar: " << bar.joinable() << '\n';
	
	  return 0;
	}

输出:
Joinable after construction:
foo: false
bar: true
Joinable after joining:
foo: false
bar: false
3.2.6、连接线程(Thread::join())
	void join();

功能:
这使该函数返回的时刻与线程中所有操作的完成同步。
阻塞调用该函数的线程的执行,直到构造函数上调用的函数返回为止(函数阻塞,直到线程执行完毕)。
线程执行完成后,该函数返回。
调用此函数后,线程对象变得不可连接,并且被安全地销毁。

返回值: void

	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 3 threads...\n";
	  std::thread t1 (pause_thread,1);
	  std::thread t2 (pause_thread,2);
	  std::thread t3 (pause_thread,3);
	  std::cout << "Done spawning threads. Now waiting for them to join:\n";
	  t1.join();
	  t2.join();
	  t3.join();
	  std::cout << "All threads joined!\n";
	
	  return 0;
	}

输出:
Spawning 3 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
All threads joined!
3.2.7、分离线程(Thread::detach())
	void detach();

功能:
从调用线程中分离对象所代表的线程,从而使它们彼此独立执行。

两个线程继续运行,而不会阻塞或以任何方式进行同步。 请注意,当任何一个执行结束时,其资源将被释放。

调用此函数后,线程对象变得不可连接,并且可以安全地被销毁。

返回值: void

	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;
	}

输出:
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
3.2.8、(Thread::swap())
	void swap (thread& x) noexcept;

功能: 用x线程对象交换当前线程对象的状态。x线程对象和当前线程对象均被修改。
返回值: void

3.2.9、(Thread::native_handle())
	native_handle_type native_handle();

功能:
获取本地句柄;如果库实现支持,则该成员函数仅存在于类线程中。如果存在,它将返回一个值,该值用于访问与线程关联的特定于实现的信息。

3.2.10、(Thread::hardware_concurrency ())
	static  unsigned  hardware_concurrency() noexcept;

功能: 检测硬件并发;返回硬件线程上下文的数量。

此值的解释是特定于系统和实现的,可能不准确,而只是一个近似值。

请注意,这不需要与系统中可用的处理器或内核的实际数量相匹配:系统可以为每个处理单元支持多个线程,或限制对程序的资源访问。

如果此值不可计算或定义不正确,则该函数返回0。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值