[原]std::thread总结

原 总结 C++11 thread

  • 缘起
  • std::thread
    • 类定义
    • 各个成员函数的简单介绍
    • 例子
  • 参考资料

缘起

从C++11开始提供了线程的支持,终于可以方便的编写跨平台的线程代码了。除了std::thread类,还提供了许多其它便利同步的机制,本篇总结是C++11学习笔记系列的首篇总结。

std::thread

std::thread定义在<thread>中,提供了方便的创建线程的功能。

类定义

  1. class thread




  2. public: 

  3. thread() noexcept; 

  4. thread( thread&& other ) noexcept; 

  5. template< class Function, class... Args > 

  6. explicit thread( Function&& f, Args&&... args ); 

  7. thread(const thread&) = delete; 

  8. ~thread(); 

  9. thread& operator=( thread&& other ) noexcept; 

  10. bool joinable() const noexcept; 

  11. std::thread::id get_id() const noexcept; 

  12. native_handle_type native_handle(); 

  13. void join(); 

  14. void detach(); 

  15. void swap( thread& other ) noexcept; 

  16. static unsigned int hardware_concurrency() noexcept; 

  17. }; 

从定义中我们可以得知:

各个成员函数的简单介绍

例子

因为thread类比较简单,我们通过几个例子来学习。

  • 支持移动语义,但不支持拷贝语义
  1. #include <thread>


  2. void some_function() {} 

  3. void some_other_function() {} 

  4. int main() 



  5. std::thread t1(some_function); // 构造一个thread对象t1 

  6. std::thread t2 = std::move(t1); // 把t1 move给另外一个thread对象t2,t1不再管理之前的线程了。 

  7. // 这句不需要std::move(),从临时变量进行移动是自动和隐式的。调用的是operator=(std::thread&&) 

  8. t1 = std::thread(some_other_function); 

  9. std::thread t3; 

  10. t3 = std::move(t2); // 把t2 move给t3 

  11. // 把t3 move给t1,非法。因为`t1`已经有了一个相关的线程,会调用`std::terminate()`来终止程序。 

  12. t1 = std::move(t3); 



  • 通过调用join()成员函数来等待线程结束
  1. #include <iostream>


  2. #include <thread> 

  3. #include <chrono> 


  4. void foo() { 

  5. std::this_thread::sleep_for(std::chrono::seconds(1)); 




  6. int main() { 

  7. std::cout << "starting first helper...\n"; 

  8. std::thread helper1(foo); 

  9. helper1.join(); 



  • 传递参数给线程函数
  1. void f(int i, std::string const& s);


  2. std::thread t(f, 3 "hello"); 

注意:参数会以默认的方式被复制到内部存储空间,直到使用的时候才会转成对应的类型。

下面的例子有问题吗?有什么问题?

  1. void f(int i, std::string const& s);


  2. void oops(int some_param) 



  3. char buffer[1024]; 

  4. sprintf(buffer, "%i", some_param); 

  5. std::thread t(f, 3, buffer); 

  6. t.detach(); 



局部变量buffer的指针会被传递给新线程,如果oops()buffer被转换成string之前退出,那么会导致未定义的行为。解决之道是在构造std::thread的时候传递string变量。std::thread t(f, 3, std::string(buffer));

因为默认会复制,如果像要传递引用,需要使用std::ref()来标识,就像std::bind()那样。

  1. std::thread t(update_data_for_widget, w, std::ref(data));


  • 使用类的成员函数作为线程参数
  1. #include <thread>


  2. #include <string> 

  3. class CRunner 



  4. public: 

  5. void run0(){} 

  6. void run1(int a) {} 

  7. void run2(int a, int b) {} 

  8. int run3(int a, char b, const std::string& c) {return 0;} 

  9. int run4(int& a, double b, float c, char d) { ++a; return 0; } 

  10. static void run_static(int a) {} 

  11. }; 


  12. int main() 



  13. CRunner runner; 

  14. int a = 0; 

  15. // 使用std::mem_fun 

  16. std::thread t0(std::mem_fun(&CRunner::run0), &runner); 

  17. // 使用std::mem_fun_ref,注意与std::mem_fun的区别 

  18. std::thread t1(std::mem_fun_ref(&CRunner::run1), std::ref(runner), 1); 

  19. // 使用std::mem_fn,std::mem_fn支持多于一个参数的函数,std::mem_fun不支持。 

  20. std::thread t2(std::mem_fn(&CRunner::run2), std::ref(runner), 1, 2); 

  21. // 使用std::bind + std::mem_fn 

  22. std::thread t3(std::bind(std::mem_fn(&CRunner::run3), &runner, 1, 2, "data"));  

  23. // 使用std::mem_fn,注意std::ref的用法,如果不用std::ref行不行? 

  24. std::thread t4(std::mem_fn(&CRunner::run4), &runner, std::ref(a), 2.2, 3.3f, ‘d‘);  

  25. // 使用类的静态函数 

  26. std::thread t5(&CRunner::run_static, 1); 


  27. t0.join(); 

  28. t1.join(); 

  29. t2.join(); 

  30. t3.join(); 

  31. t4.join(); 

  32. t5.join(); 



参考资料

原文地址:https://www.cnblogs.com/bianchengnan/p/9459490.html

时间: 2024-10-06 03:57:56

[原]std::thread总结的相关文章

C++——多线程编程(一)std::thread

(一)与C++11多线程相关的头文件 C++11 新标准中引入了四个头文件来支持多线程编程,他们分别是< atomic> ,< thread>,< mutex>,< condition_variable>和< future>. ?< atomic>:该头文主要声明了两个类, std::atomic 和 std::atomic_flag,另外还声明了一套 C 风格的原子类型和与 C 兼容的原子操作的函数. ?< thread>

std::thread(2)

个线程都有一个唯一的 ID 以识别不同的线程,std:thread 类有一个 get_id() 方法返回对应线程的唯一编号,你可以通过 std::this_thread 来访问当前线程实例,下面的例子演示如何使用这个 id: #include <thread> #include <iostream> #include <vector> void hello(){ std::cout << "Hello from thread " <

C++11多线程std::thread的简单使用

转自:http://blog.csdn.net/star530/article/details/24186783 在cocos2dx 2.0时代,我们使用的是pthread库,是一套用户级线程库,被广泛地使用在跨平台应用上.但在cocos2dx 3.0中并未发现有pthread的支持文件,原来c++11中已经拥有了一个更好用的用于线程操作的类std::thread.cocos2dx 3.0的版本默认是在vs2012版本,支持c++11的新特性,使用std::thread来创建线程简直方便. 下面

用std::thread替换实现boost::thread_group

thread_group是boost库中的线程池类,内部使用的是boost::thread. 随着C++ 11标准的制定和各大编译器的新版本的推出(其实主要是VS2012的推出啦……),本着能用标准库就用标准库的指导原则,决定把项目中多线程相关的部分代码从boost::thread迁移到std::thread. thread的迁移本身很简单,毕竟stl的很多功能是直接从boost发展而来的,基本上就是改一下头文件和名称空间的问题,例外是thread_group,thread_group是boos

C++11 并发指南------std::thread 详解

参考: https://github.com/forhappy/Cplusplus-Concurrency-In-Practice/blob/master/zh/chapter3-Thread/Introduction-to-Thread.md#stdthread-%E8%AF%A6%E8%A7%A3 本节将详细介绍 std::thread 的用法. std::thread 在 <thread> 头文件中声明,因此使用 std::thread 需包含 <thread> 头文件. &

Cocos2dx 3.0 过渡篇(二十七)C++11多线程std::thread的简单使用(下)

本篇接上篇继续讲:上篇传送门:http://blog.csdn.net/star530/article/details/24186783 简单的东西我都说的几乎相同了,想挖点深的差点把自己给填进去. 以下实际演练一下.请同意我參考偶尔E往事的一篇线程的博客, 他用的是pThread.这里我就用std::thread. 1.售票孙鑫老师的C++和Java多线程售票也一直让我念念不忘(好吧,我承认我没看过).这里用cocos2d-x3.0和C++11的std::thread实现一个吧.总共同拥有10

std::thread “terminate called without an active exception”

最近在使用std::thread的时候,遇到这样一个问题: std::thread t(func); 如果不使用调用t.join()就会遇到 "terminate called whithout an active exception",但是在使用boost:thread的时候却没遇到这个问题,google了一下,找到答案: The trouble you are encountering is a result of the stopThread going out of scope

mingw-w64线程模型:posix vs win32(posix允许使用c++11的std:: thread,但要带一个winpthreads,可能需要额外dll)

我正在安装 mingw-w64 on Windows,有两个选项: win32线程和posix线程. 我知道win32线程和pthreads之间的区别,但是我不明白这两个选项之间的区别. 我怀疑如果我选择了posix线程,它将阻止我调用像CreateThread这样的WinAPI函数. 似乎这个选项指定了哪个程序或者库将使用哪个线程 API,但通过什么? 由 GCC,libstdc++或者其他事物? 我发现:什么区别thread_posixs和 thread_win32 gcc Windows

C++11 std::thread在类的成员函数中的使用

#include <thread> #include <iostream> class Wrapper { public: void member1() { std::cout << "i am member1" << std::endl; } void member2(const char *arg1, unsigned arg2) { std::cout << "i am member2 and my first