原 总结 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. html通配符

    ♠ ♠ ♠ 黑桃 ♣ ♣ ♣ 梅花 ♥ ♥ ♥ 红桃,心 ♦ ♦ ♦ 方块牌 ◊ ◊ ◊ 菱形 † † † 匕首 ‡ ‡ ‡ 双剑号 ¡ ¡ ¡ 反向感叹号 ¿ ¿ ¿ 反向问号 ← ← ← 左箭头 ...

  2. java课程课后作业190502之单词统计续集

    第1步:输出单个文件中的前 N 个最常出现的英语单词. 功能1:输出文件中所有不重复的单词,按照出现次数由多到少排列,出现次数同样多的,以字典序排列. 功能2: 指定文件目录,对目录下每一个文件执行统 ...

  3. 对spring中IOC和AOP的理解

    IOC:控制反转也叫依赖注入.利用了工厂模式. 为了方便理解,分解成每条以便记忆.  1.将对象交给容器管理,你只需要在spring配置文件总配置相应的bean,以及设置相关的属性,让spring容器 ...

  4. centos7 lvm合并分区脚本初探-linux性能测试 -centos7修改网卡名字-jdk环境安装脚本-关键字查询文件-批量添加用户

    1.#!/bin/bash lvmdiskscan | grep centos > /root/a.txt a=`sed -n '1p' /root/a.txt` b=`sed -n '2p' ...

  5. 从架构师视角看是否该用Kotlin做服务端开发?

    前言 自从Oracle收购Sun之后,对Java收费或加强控制的尝试从未间断,谷歌与Oracle围绕Java API的官司也跌宕起伏.虽然Oracle只是针对Oracle JDK8的升级收费,并释放了 ...

  6. Oracle 中多个字段显示成一列

    SELECT COALESCE(A,B,C,'NA') FROM XXXXX --判断A若为空则取B,B为空这取C,C为空则取默认值'NA'

  7. mysql第三篇:表操作

    第三篇:表操作 一.什么是表 表相当于文件,表中的一条记录就相当于文件的一行内容,不同的是,表中的一条记录有对应的标题,称为表的字段 二.创建表 语法 CREATE TABLE 表名( 字段名1 类型 ...

  8. Vue-router(1)之component标签

    1. 使用 <component>标签实现组件切换 <component> 是Vue提供的标签语法:有一个is属性,is的作用就是显示指定的组件 <template> ...

  9. 【每日Scrum】第四天冲刺

    一.计划会议内容 连接数据库报错,解决问题中. 二.任务看板 三.scrum讨论照片 四.产品的状态 无 五.任务燃尽图  

  10. winform屏蔽鼠标右键

    /// <summary> /// 屏蔽右键 /// </summary> internal class MenuHandler : IContextMenuHandler { ...