C++11并发之std::thread
知识链接:
C++11 并发之std::mutex
C++11 并发之std::atomic
本文概要:
1、成员类型和成员函数。
2、std::thread 构造函数。
3、异步。
4、多线程传递参数。
5、join、detach。
6、获取CPU核心个数。
7、CPP原子变量与线程安全。
8、lambda与多线程。
9、时间等待相关问题。
10、线程功能拓展。

11、多线程可变参数。
12、线程交换。
13、线程移动。

std::thread 在 #include<thread> 头文件中声明,因此使用 std::thread 时需要包含 #include<thread> 头文件。
1、成员类型和成员函数。
成员类型:
id
Thread id (public member type )                                       id
native_handle_type
Native handle type (public member type )

成员函数:

(constructor)
Construct thread (public member function )        构造函数
(destructor)
Thread destructor (public member function )      析构函数
operator=
Move-assign thread (public member function )  赋值重载
get_id
Get thread id (public member function )                获取线程id
joinable
Check if joinable (public member function )          判断线程是否可以加入等待
join
Join thread (public member function )                    加入等待
detach
Detach thread (public member function )              分离线程
swap
Swap threads (public member function )               线程交换
native_handle
Get native handle (public member function )       获取线程句柄
hardware_concurrency [static]
Detect hardware concurrency (public static member function )   检测硬件并发特性

Non-member overloads:

swap (thread)
Swap threads (function )

2、std::thread 构造函数。
如下表:
default (1)
thread() noexcept;
initialization(2)
template <class Fn, class... Args>   explicit thread (Fn&& fn, Args&&... args);
copy [deleted] (3)
thread (const thread&) = delete;
move [4]
hread (thread&& x) noexcept;
(1).默认构造函数,创建一个空的 thread 执行对象。
(2).初始化构造函数,创建一个 thread 对象,该 thread 对象可被 joinable,新产生的线程会调用 fn 函数,该函数的参数由 args 给出。
(3).拷贝构造函数(被禁用),意味着 thread 不可被拷贝构造。
(4).move 构造函数,move 构造函数,调用成功之后 x 不代表任何 thread 执行对象。
注意:可被 joinable 的 thread 对象必须在他们销毁之前被主线程 join 或者将其设置为 detached。

std::thread 各种构造函数例子如下:
[cpp] view plain copy
  1. <span style="font-size:12px;">#include<iostream>
  2. #include<thread>
  3. #include<chrono>
  4. using namespace std;
  5. void fun1(int n)  //初始化构造函数
  6. {
  7. cout << "Thread " << n << " executing\n";
  8. n += 10;
  9. this_thread::sleep_for(chrono::milliseconds(10));
  10. }
  11. void fun2(int & n) //拷贝构造函数
  12. {
  13. cout << "Thread " << n << " executing\n";
  14. n += 20;
  15. this_thread::sleep_for(chrono::milliseconds(10));
  16. }
  17. int main()
  18. {
  19. int n = 0;
  20. thread t1;               //t1不是一个thread
  21. thread t2(fun1, n + 1);  //按照值传递
  22. t2.join();
  23. cout << "n=" << n << '\n';
  24. n = 10;
  25. thread t3(fun2, ref(n)); //引用
  26. thread t4(move(t3));     //t4执行t3,t3不是thread
  27. t4.join();
  28. cout << "n=" << n << '\n';
  29. return 0;
  30. }
  31. 运行结果:
  32. Thread 1 executing
  33. n=0
  34. Thread 10 executing
  35. n=30</span>
3、异步。
例如:
[cpp] view plain copy
  1. <span style="font-size:12px;">#include<iostream>
  2. #include<thread>
  3. using namespace std;
  4. void show()
  5. {
  6. cout << "hello cplusplus!" << endl;
  7. }
  8. int main()
  9. {
  10. //栈上
  11. thread t1(show);   //根据函数初始化执行
  12. thread t2(show);
  13. thread t3(show);
  14. //线程数组
  15. thread th[3]{thread(show), thread(show), thread(show)};
  16. //堆上
  17. thread *pt1(new thread(show));
  18. thread *pt2(new thread(show));
  19. thread *pt3(new thread(show));
  20. //线程指针数组
  21. thread *pth(new thread[3]{thread(show), thread(show), thread(show)});
  22. return 0;
  23. }</span>
4、多线程传递参数。
例如:
[cpp] view plain copy
  1. <span style="font-size:12px;">#include<iostream>
  2. #include<thread>
  3. using namespace std;
  4. void show(const char *str, const int id)
  5. {
  6. cout << "线程 " << id + 1 << " :" << str << endl;
  7. }
  8. int main()
  9. {
  10. thread t1(show, "hello cplusplus!", 0);
  11. thread t2(show, "你好,C++!", 1);
  12. thread t3(show, "hello!", 2);
  13. return 0;
  14. }
  15. 运行结果:
  16. 线程 1线程 2 :你好,C++!线程 3 :hello!
  17. :hello cplusplus!</span>
发现,线程 t1、t2、t3 都执行成功!
5、join、detach。
join例子如下:
[cpp] view plain copy
  1. <span style="font-size:12px;">#include<iostream>
  2. #include<thread>
  3. #include<array>
  4. using namespace std;
  5. void show()
  6. {
  7. cout << "hello cplusplus!" << endl;
  8. }
  9. int main()
  10. {
  11. array<thread, 3>  threads = { thread(show), thread(show), thread(show) };
  12. for (int i = 0; i < 3; i++)
  13. {
  14. cout << threads[i].joinable() << endl;//判断线程是否可以join
  15. threads[i].join();//主线程等待当前线程执行完成再退出
  16. }
  17. return 0;
  18. }
  19. 运行结果:
  20. hello cplusplus!
  21. hello cplusplus!
  22. 1
  23. hello cplusplus!
  24. 1
  25. 1</span>
总结:
join 是让当前主线程等待所有的子线程执行完,才能退出。
detach例子如下:

[cpp] view plain copy
  1. <span style="font-size:12px;">#include<iostream>
  2. #include<thread>
  3. using namespace std;
  4. void show()
  5. {
  6. cout << "hello cplusplus!" << endl;
  7. }
  8. int main()
  9. {
  10. thread th(show);
  11. //th.join();
  12. th.detach();//脱离主线程的绑定,主线程挂了,子线程不报错,子线程执行完自动退出。
  13. //detach以后,子线程会成为孤儿线程,线程之间将无法通信。
  14. cout << th.joinable() << endl;
  15. return 0;
  16. }
  17. 运行结果:
  18. hello cplusplus!
  19. 0</span>
结论:
线程 detach 脱离主线程的绑定,主线程挂了,子线程不报错,子线程执行完自动退出。
线程 detach以后,子线程会成为孤儿线程,线程之间将无法通信。

6、获取CPU核心个数。
例如:
[cpp] view plain copy
  1. <span style="font-size:12px;">#include<iostream>
  2. #include<thread>
  3. using namespace std;
  4. int main()
  5. {
  6. auto n = thread::hardware_concurrency();//获取cpu核心个数
  7. cout << n << endl;
  8. return 0;
  9. }
  10. 运行结果:
  11. 8</span>
结论:
通过  thread::hardware_concurrency() 获取 CPU 核心的个数。
7、CPP原子变量与线程安全。
问题例如:
[cpp] view plain copy
  1. <span style="font-size:12px;">#include<iostream>
  2. #include<thread>
  3. using namespace std;
  4. const int N = 100000000;
  5. int num = 0;
  6. void run()
  7. {
  8. for (int i = 0; i < N; i++)
  9. {
  10. num++;
  11. }
  12. }
  13. int main()
  14. {
  15. clock_t start = clock();
  16. thread t1(run);
  17. thread t2(run);
  18. t1.join();
  19. t2.join();
  20. clock_t end = clock();
  21. cout << "num=" << num << ",用时 " << end - start << " ms" << endl;
  22. return 0;
  23. }
  24. 运行结果:
  25. num=143653419,用时 730 ms</span>
从上述代码执行的结果,发现结果并不是我们预计的200000000,这是由于线程之间发生冲突,从而导致结果不正确。
为了解决此问题,有以下方法:
(1)互斥量。
例如:
[cpp] view plain copy
  1. <span style="font-size:12px;">#include<iostream>
  2. #include<thread>
  3. #include<mutex>
  4. using namespace std;
  5. const int N = 100000000;
  6. int num(0);
  7. mutex m;
  8. void run()
  9. {
  10. for (int i = 0; i < N; i++)
  11. {
  12. m.lock();
  13. num++;
  14. m.unlock();
  15. }
  16. }
  17. int main()
  18. {
  19. clock_t start = clock();
  20. thread t1(run);
  21. thread t2(run);
  22. t1.join();
  23. t2.join();
  24. clock_t end = clock();
  25. cout << "num=" << num << ",用时 " << end - start << " ms" << endl;
  26. return 0;
  27. }
  28. 运行结果:
  29. num=200000000,用时 128323 ms</span>
不难发现,通过互斥量后运算结果正确,但是计算速度很慢,原因主要是互斥量加解锁需要时间。
互斥量详细内容 请参考C++11 并发之std::mutex。
(2)原子变量。
例如:
[cpp] view plain copy
  1. <span style="font-size:12px;">#include<iostream>
  2. #include<thread>
  3. #include<atomic>
  4. using namespace std;
  5. const int N = 100000000;
  6. atomic_int num{ 0 };//不会发生线程冲突,线程安全
  7. void run()
  8. {
  9. for (int i = 0; i < N; i++)
  10. {
  11. num++;
  12. }
  13. }
  14. int main()
  15. {
  16. clock_t start = clock();
  17. thread t1(run);
  18. thread t2(run);
  19. t1.join();
  20. t2.join();
  21. clock_t end = clock();
  22. cout << "num=" << num << ",用时 " << end - start << " ms" << endl;
  23. return 0;
  24. }
  25. 运行结果:
  26. num=200000000,用时 29732 ms</span>
不难发现,通过原子变量后运算结果正确,计算速度一般。
原子变量详细内容 请参考C++11 并发之std::atomic。
(3)加入 join 。
例如:
[cpp] view plain copy
  1. <span style="font-size:12px;">#include<iostream>
  2. #include<thread>
  3. using namespace std;
  4. const int N = 100000000;
  5. int num = 0;
  6. void run()
  7. {
  8. for (int i = 0; i < N; i++)
  9. {
  10. num++;
  11. }
  12. }
  13. int main()
  14. {
  15. clock_t start = clock();
  16. thread t1(run);
  17. t1.join();
  18. thread t2(run);
  19. t2.join();
  20. clock_t end = clock();
  21. cout << "num=" << num << ",用时 " << end - start << " ms" << endl;
  22. return 0;
  23. }
  24. 运行结果:
  25. num=200000000,用时 626 ms</span>
不难发现,通过原子变量后运算结果正确,计算速度也很理想。
8、lambda与多线程。
例如:
[cpp] view plain copy
  1. <span style="font-size:12px;">#include<iostream>
  2. #include<thread>
  3. using namespace std;
  4. int main()
  5. {
  6. auto fun = [](const char *str) {cout << str << endl; };
  7. thread t1(fun, "hello world!");
  8. thread t2(fun, "hello beijing!");
  9. return 0;
  10. }
  11. 运行结果:
  12. hello world!
  13. hello beijing!</span>
9、时间等待相关问题。
例如:
[cpp] view plain copy
  1. <span style="font-size:12px;">#include<iostream>
  2. #include<thread>
  3. #include<chrono>
  4. using namespace std;
  5. int main()
  6. {
  7. thread th1([]()
  8. {
  9. //让线程等待3秒
  10. this_thread::sleep_for(chrono::seconds(3));
  11. //让cpu执行其他空闲的线程
  12. this_thread::yield();
  13. //线程id
  14. cout << this_thread::get_id() << endl;
  15. });
  16. return 0;
  17. }</span>
10、线程功能拓展。
例如:
[cpp] view plain copy
  1. <span style="font-size:12px;">#include<iostream>
  2. #include<thread>
  3. using namespace std;
  4. class MyThread :public thread   //继承thread
  5. {
  6. public:
  7. //子类MyThread()继承thread()的构造函数
  8. MyThread() : thread()
  9. {
  10. }
  11. //MyThread()初始化构造函数
  12. template<typename T, typename...Args>
  13. MyThread(T&&func, Args&&...args) : thread(forward<T>(func), forward<Args>(args)...)
  14. {
  15. }
  16. void showcmd(const char *str)  //运行system
  17. {
  18. system(str);
  19. }
  20. };
  21. int main()
  22. {
  23. MyThread th1([]()
  24. {
  25. cout << "hello" << endl;
  26. });
  27. th1.showcmd("calc"); //运行calc
  28. //lambda
  29. MyThread th2([](const char * str)
  30. {
  31. cout << "hello" << str << endl;
  32. }, " this is MyThread");
  33. th2.showcmd("notepad");//运行notepad
  34. return 0;
  35. }
  36. 运行结果:
  37. hello
  38. //运行calc
  39. hello this is MyThread
  40. //运行notepad</span>
11、多线程可变参数。
例如:
[cpp] view plain copy
  1. <span style="font-size:12px;">#include<iostream>
  2. #include<thread>
  3. #include<cstdarg>
  4. using namespace std;
  5. int show(const char *fun, ...)
  6. {
  7. va_list ap;//指针
  8. va_start(ap, fun);//开始
  9. vprintf(fun, ap);//调用
  10. va_end(ap);
  11. return 0;
  12. }
  13. int main()
  14. {
  15. thread t1(show, "%s    %d    %c    %f", "hello world!", 100, 'A', 3.14159);
  16. return 0;
  17. }
  18. 运行结果:
  19. hello world!    100    A    3.14159</span>
12、线程交换。
例如:
[cpp] view plain copy
  1. <span style="font-size:12px;">#include<iostream>
  2. #include<thread>
  3. using namespace std;
  4. int main()
  5. {
  6. thread t1([]()
  7. {
  8. cout << "thread1" << endl;
  9. });
  10. thread t2([]()
  11. {
  12. cout << "thread2" << endl;
  13. });
  14. cout << "thread1' id is " << t1.get_id() << endl;
  15. cout << "thread2' id is " << t2.get_id() << endl;
  16. cout << "swap after:" << endl;
  17. swap(t1, t2);//线程交换
  18. cout << "thread1' id is " << t1.get_id() << endl;
  19. cout << "thread2' id is " << t2.get_id() << endl;
  20. return 0;
  21. }
  22. 运行结果:
  23. thread1
  24. thread2
  25. thread1' id is 4836
  26. thread2' id is 4724
  27. swap after:
  28. thread1' id is 4724
  29. thread2' id is 4836</span>
两个线程通过 swap 进行交换。
13、线程移动。
例如:
[cpp] view plain copy
  1. <span style="font-size:12px;">#include<iostream>
  2. #include<thread>
  3. using namespace std;
  4. int main()
  5. {
  6. thread t1([]()
  7. {
  8. cout << "thread1" << endl;
  9. });
  10. cout << "thread1' id is " << t1.get_id() << endl;
  11. thread t2 = move(t1);;
  12. cout << "thread2' id is " << t2.get_id() << endl;
  13. return 0;
  14. }
  15. 运行结果:
  16. thread1
  17. thread1' id is 5620
  18. thread2' id is 5620</span>
从上述代码中,线程t2可以通过 move 移动 t1 来获取 t1 的全部属性,而 t1 却销毁了。

转载于:https://www.cnblogs.com/mmc9527/p/10427924.html

C++11并发之std::thread相关推荐

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

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

  2. C++11 多线程(std::thread)详解

    注:此教程以 Visual Studio 2019 Version 16.10.3 (MSVC 19.29.30038.1) 为标准,大多数内容参照cplusplus.com里的解释 此文章允许转载, ...

  3. std::thread使用

    c++ 11 之后有了标准的线程库:std::thread.通过c++11中的线程库创建线程,极为方便,且跨平台,是语言层面的.之前跨平台的多线程开发中,多使用boost 相关第三方库. 1.std: ...

  4. C++11中头文件thread的使用

    C++11中加入了<thread>头文件,此头文件主要声明了std::thread线程类.C++11的标准类std::thread对线程进行了封装.std::thread代表了一个线程对象 ...

  5. C++多线程编程实战01:std::thread

    C++多线程:std::thread 文章目录 C++多线程:std::thread 定义 构造函数 析构函数 赋值操作函数 join与datch 例子 例子 其它 基本用法 线程参数 等待线程完成( ...

  6. std::thread与pthread

    线程std::thread与pthread对比 多线程是多任务处理的一种特殊形式,多任务处理允许让电脑同时运行两个或两个以上的程序.一般情况下,两种类型的多任务处理:基于进程和基于线程. 基于进程的多 ...

  7. C++多线程:std::thread

    最近这段时间在学习C++多线程相关的知识,打算将学习的内容记录下来,加深理解和记忆. C++11 新标准中引入了五个头文件来支持多线程编程,他们分别是<atomic> ,<threa ...

  8. C++11 新特性之std::thread

    C++11 新特性之std::thread 原文:https://blog.csdn.net/oyoung_2012/article/details/78958274 从C++11开始,C++标准库已 ...

  9. 【多线程】C++11进行多线程开发 (std::thread)

    文章目录 创建线程 std::thread 类 使用join() 使用 detach() 警惕作用域 线程不能复制 给线程传参 传递指针 传递引用 以类成员函数为线程函数 以容器存放线程对象 互斥量 ...

最新文章

  1. 教AI区分因果关系和相关性,将改变下一代 AI 的研发
  2. 也谈淘点点60s短信订单的架构设计
  3. Java黑皮书课后题第8章:*8.30(代数:解答线性方程)编写一个方法,解答下面的2*2线性方程组系统
  4. Java8新特性之Lambda
  5. php为什么凉了_马蜂窝裁php换java,php又又又凉凉了吗
  6. Wi-Fi 6还没用上,Wi-Fi 7就要来了?
  7. 解决Conda install tensorflow弹窗Python.exe已经停止工作的问题
  8. 获取北京时间 日开始时间戳
  9. Win7 安装 -- SHSUCDX can’t install 问题解决
  10. android 当手柄打游戏,玩手游需不需要配手柄?谈移动游戏外设的三个机会
  11. 车间和仓库可以一起吗_为什么厂房和仓库不能混用?
  12. 女篮亚军,为啥男篮那么水?
  13. [Unity3D] Unity3D连接安卓设备调试unity程序
  14. 【leetcode】 剑指 Offer学习计划(java版本含注释)(上)
  15. 统计学怎么求加权指数_暨南大学《统计学》中文习题 第十二章 统计指数
  16. 简单了解软件开发的生命周期和流程、思想
  17. 手机测试android程序下载,测手速下载_测手速手机版下载「安卓版」-太平洋下载中心...
  18. Parallelism , Partitioner
  19. 我眼中的互联网运营感观——运营是什么?
  20. 有趣的智能图像处理demo汇总

热门文章

  1. CSS 相对|绝对(relative/absolute)定位系列(二)
  2. CSS之background-size属性
  3. grid比flex更强大的属性
  4. std::function和std::bind
  5. c++ fork 进程时 共享内存_c/c++ Linux 进程间通信------共享内存
  6. css ——行级元素与块级元素解析
  7. openstack placement 组件作用理解
  8. mysql批量生成修改表和列注释语句
  9. 用nodejs 替换文件中所有图片的url
  10. 基于visual Studio2013解决C语言竞赛题之0304整除数