原 总结 C++11 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) const {} 

  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,可以传引用或副本 

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

  19. // std::thread t1(std::mem_fun_ref(&CRunner::run1), runner, 1); 


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

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

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

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

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

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

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

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


  28. t0.join(); 

  29. t1.join(); 

  30. t2.join(); 

  31. t3.join(); 

  32. t4.join(); 

  33. t5.join(); 



注:

更多

虽然在之前的例子中的函数有返回值,但是我们却不能获得,想获得返回值我们需要使用std::future,关于std::future的总结,后续会慢慢补充,敬请期待。

参考资料

[原]C++新标准之std::thread的更多相关文章

  1. [原]C++新标准之std::chrono::duration

    原 总结 C++11 chrono duration ratio  概览 std::chrono::duration 描述 类定义 duration_cast()分析 预定义的duration 示例代 ...

  2. [原]C++新标准之std::chrono::time_point

    原 总结 STL 标准库 chrono time_point ratio  概览 类定义 总结 思考 拓展 system_clock steady_clock high_resolution_cloc ...

  3. [原]C++新标准之std::ratio

    原 总结 ratio  概览 类定义 预定义ratio 应用 示例代码 参考资料 概览 std::ratio定义在<ratio>文件中,提供了编译期的比例计算功能.为std::chrono ...

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

    我正在安装 mingw-w64 on Windows,有两个选项: win32线程和posix线程. 我知道win32线程和pthreads之间的区别,但是我不明白这两个选项之间的区别. 我怀疑如果我 ...

  5. C++ std::thread概念介绍

    C++ 11新标准中,正式的为该语言引入了多线程概念.新标准提供了一个线程库thread,通过创建一个thread对象来管理C++程序中的多线程. 本文简单聊一下C++多线程相关的一些概念及threa ...

  6. 第25课 std::thread对象的析构

    一. 线程的等待与分离 (一)join和detach函数 1. 线程等待:join() (1)等待子线程结束,调用线程处于阻塞模式. (2)join()执行完成之后,底层线程id被设置为0,即join ...

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

    参考: https://github.com/forhappy/Cplusplus-Concurrency-In-Practice/blob/master/zh/chapter3-Thread/Int ...

  8. std::thread使用

    本文将从以下三个部分介绍C++11标准中的thread类,本文主要内容为: 启动新线程 等待线程与分离线程 线程唯一标识符 1.启动线程 线程再std::threada对象创建时启动.最简单的情况下, ...

  9. C++11并发——多线程std::thread (一)

    https://www.cnblogs.com/haippy/p/3284540.html 与 C++11 多线程相关的头文件 C++11 新标准中引入了四个头文件来支持多线程编程,他们分别是< ...

随机推荐

  1. Hibernate--(二)增删改查

    1.增删改查: public class Test { public static void main(String[] args) { SessionFactory sf = new Configu ...

  2. Hadoop家族系统学习路线

    本文主要介绍Hadoop家族产品,常用的项目包括Hadoop,Hive,Pig,HBase,Sqoop,Mahout,Zookeeper,Avro,Ambari,Chukwa,新增加的项目包括,YAR ...

  3. 快速幂的类似问题(51Nod 1008 N的阶乘 mod P)

    下面我们来看一个容易让人蒙圈的问题:N的阶乘 mod P. 51Nod 1008 N的阶乘 mod P 看到这个可能有的人会想起快速幂,快速幂是N的M次方 mod P,这里可能你就要说你不会做了,其实 ...

  4. Nginx之epoll和select poll

    epoll和 select poll 都是做I/O多路复用的. 区别在于: epoll较灵活,如果有一百万个链接状态同时保持,但是在某个时刻,只有几百个链接是活跃的.epoll的处理是通过epoll_ ...

  5. POJ 2014:Flow Layout 模拟水题

    Flow Layout Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 3091   Accepted: 2148 Descr ...

  6. spring aop中的propagation的7种配置

    1.前言 在声明式的事务处理中,要配置一个切面,即一组方法,如 <tx:advice id="txAdvice" transaction-manager="txMa ...

  7. 计算广告-GD广告

    算法 分配算法主要是解优化问题. 流量预测(traffic forecasting), 流量预估 库存分配, 粗力度的分配. 流量分配, 排单算法 在线分配(Online Allocation) 资料 ...

  8. Neo4j图形数据库备份

    Neo4j图形数据库备份 backup.sh文件 nowtime=`date +"%Y-%m-%d_%H_%M"` #原文件路径 sourcepath='/home/neo4j/n ...

  9. Java中常用的API(一)——Object

    概述 如果要问Java为什么是用起来非常舒服的语言,那很大一部分的功劳就是JavaAPI的.API定义了许多封装好的类和方法供我们使用,来处理特定的问题,所以学习常用的API是非常重要的. 同时,面向 ...

  10. JZOJ-TG817-A-solution

    T1 考虑是否有一种排序方法使得最优解都相邻,这种排序方法就是按照过一个点x的斜率为(P/Q)的直线的截距 排序之后考虑临项即可,O(N) T2 exit