原 总结 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. jetty启动项目后js修改后无法保存

    在web.xml中加入如下配置即可: <servlet> <servlet-name>default</servlet-name> <servlet-clas ...

  2. 安装Linux系统Centos6版本

    1.下载VMware软件 2.下载Centos6文件 http://archive.kernel.org/centos-vault/6.8/isos/x86_64/CentOS-6.8-x86_64- ...

  3. Python基础+爬虫基础

    Python基础+爬虫基础 一.python的安装: 1.建议安装Anaconda,会自己安装一些Python的类库以及自动的配置环境变量,比较方便. 二.基础介绍 1.什么是命名空间:x=1,1存在 ...

  4. 2.6 UI控件与后台联系实现

    完成的结果如下 : 当点击 左按钮时 最上边的显示栏更改为左 反之则为右  点击开关显示为开或者关 下边两个为显示加载的界面 在输入栏输入数值可以控制进度条的百分比并且显示在最上边 点击图片一二切换图 ...

  5. 《新标准C++程序设计》1.7-1.10(C++学习笔记2)

    1.内联函数(inline关键字) eg.inline int Max(int a,int b) { if(a>b) return a; return b; } 当编译器处理调用内联函数的语句时 ...

  6. 第二章,C语言概述

    2.1 简单的C程序示例 #include <stdio.h> #include <stdlib.h> int main(void) { int num; num=; prin ...

  7. HDU 5423:Rikka with Tree Dijkstra算法

    Rikka with Tree  Accepts: 207  Submissions: 815  Time Limit: 2000/1000 MS (Java/Others)  Memory Limi ...

  8. 工程日记之ChildLost(1):URLSession

    URLSession 是什么 URL Loading System提供了访问URL资源的系统,提供了访问http/https/自定义URL访问的接口.其中,URLSession实例可以创建多个URLS ...

  9. transform—3D立方体

    1.思路分析 第一步:首先需要一个大盒子,承载立方体的六个面: 第二步:立方体的六个面需要3D转化在特定的位置,拼接成一个立方体: 第三步:设置动画: 2.代码实现 第一步:创建div并且设置样式: ...

  10. WOJ 1538 Stones II 转化背包问题

    昨天是我负责这个题目的,最后没搞出来,真的给队伍拖后腿了. 当时都推出来了 我假设最后结果是取了m个物品,则我把这个m个物品按取的先后编号为 k1 k2 k3 k4...km 则最终结果就是 (k1. ...