文章目录

    • part 0:多线程简介
    • part 1:多线程构造
      • 它用于构造线程对象。
      • 参量
    • part 2:多线程析构
      • 它破坏线程对象。
    • part 3:多线程operator=
      • 参量 Parameters
      • 返回值
  • Data races
    • part 4:joinable 它返回线程ive对象是否可连接,则返回true,否则返回false。 表示的是否可连接状态.
    • part 5:多线程std :: thread :: get_id
      • Declaration
    • C++11
    • part 6:native_handle 返回底层实现定义的线程句柄
    • part 7:hardware_concurrency 返回实现支持的并发线程数
      • Description
      • Return Value
    • part 8:join 线程执行完成后返回
    • part 9:detach 容许线程从线程句柄独立开来执行
      • Description
    • part 10:swap 交换二个 `thread` 对象
      • Description
      • Declaration
    • part 11:std::swap 特化 [std::swap](https://zh.cppreference.com/w/cpp/algorithm/swap) 算法
      • Description
      • Declaration
      • Parameters
      • 实例:
  • 小结:
    • **当线程不需要相互依赖,不会产生数据竞争,或不是流水的实现思路下,用detach();**
    • **当可能产生数据竞争,数据之间相互依赖,算法实现设计为流水的情况下,使用join()函数,使其他线程进入阻塞状态。**

part 0:多线程简介

Thread是一个指令序列,它可以在多线程环境中与其他这样的序列同时执行,同时共享同一个地址空间。

Thread is a sequence of instructions that can be executed concurrently with other such sequences in multithreading environments, while sharing a same address spac.

Member types Description 成员类型
id It is a values of this type are returned by thread::get_id and this_thread::get_id to identify threads. It is a thread id.表示线程的id 1
native_handle_type It is a member type and it presents in class thread if the library implementation supports it. 实现定义It is a native handle type. 2
Member functions 成员函数
constructor It is used to construct thread. 构造新的 thread 对象 3
destructor It is used to destructor thread. 析构 thread 对象,必须合并或分离底层线程 4
operator= It is a move-assign thread. 移动 thread 对象 5
get_id It is used to get thread id. 返回线程的 *id 6
joinable It is used to check if joinable. 检查线程是否可合并,即潜在地运行于平行环境中 7
join It is used to join thread. 等待线程完成其执行 8
detach It is used to detach thread. 容许线程从线程句柄独立开来执行 9
swap It is used to swap threads. 交换二个 thread 对象 10
native_handle It is used to get native handle. 返回底层实现定义的线程句柄 11
hardware_concurrency It is used to detect hardware concurrency. 返回实现支持的并发线程数 12
Non-member overload & description 非成员函数
swap It is used to swap threads. 特化 std::swap 算法 13

part 1:多线程构造

它用于构造线程对象。

It is used to constructs a thread object.

以下是std :: thread :: thread函数的声明。

thread() noexcept;
template <class Fn, class... Args>
explicit thread (Fn&& fn, Args&&... args);
thread (const thread&) = delete;
thread (thread&& x) noexcept;

参量

  • **fn-**它是函数的指针,成员的指针或任何可移动构造的函数对象。
  • **args …-**传递给fn调用的参数。
  • **x-**这是一个线程对象。
#include <thread> //头文件
#include <iostream>
using namespace std;void fn1(void)
{cout << "fn1" << endl;
}void fn2(int a)
{cout << "fn2 " << a << endl;
}void fn3(int& a)
{cout << "fn3 " << a << endl;
}class cls
{
public:void fn1(int a){cout << "cls::fn1" << endl;}
};void test01() {std::thread t1(&fn1); //线程对象构造后,即开始执行//可被 joinable 的 thread 对象必须在他们销毁之前被主线程 join 或者将其设置为 detachedt1.join(); //必须执行join,不然运行期错误std::thread t2(&fn2, 2); //传入函数参数t2.join();int n = 2;std::thread t3(&fn3, std::ref(n)); //传入引用参数t3.join();cls c;//线程入口为类成员函数std::thread t4(&cls::fn1, &c, 2);t4.join();
}
int main()
{test01();getchar();return 0;
}

cpp多线程并发 头文件的使用,正则化实现

#include <iostream>
#include <thread>int main(void)
{std::thread x([]()->void {int i = 4;while (i--){std::this_thread::sleep_for(std::chrono::seconds(2));std::cout << "*" << std::endl;}return;});std::thread y([]()->void {int i = 4;while (i--){std::this_thread::sleep_for(std::chrono::seconds(5));std::cout << "-" << std::endl;}return;});std::cout << std::thread::hardware_concurrency() << std::endl; //检测计算机并发数std::cout << "x.hand " << x.native_handle() << std::endl;std::cout << "y.hand " << y.native_handle() << std::endl;//脱离主线程后不能直接获取句柄,所以放输出语句后面后面x.detach();y.detach();std::this_thread::sleep_for(std::chrono::seconds(30));//等待程序执行完成return 0;
}

part 2:多线程析构

它破坏线程对象。

It destroys the thread object. Following is the declaration for std::thread::~thread function.

~thread();

part 3:多线程operator=

以下是std :: thread :: operator =函数的声明。

It is used to move-assign thread. Following is the declaration for std::thread::operator= function.

thread& operator= (thread&& rhs) noexcept;
thread& operator= (const thread&) = delete;

参量 Parameters

rhs − It is a othread object.

RHS -这是一个othread对象。

返回值

它返回* this

Data races

rhs和对象均被修改。

Both rhs and the object are modified.

part 4:joinable 它返回线程ive对象是否可连接,则返回true,否则返回false。 表示的是否可连接状态.

It returns whether the thread object is joinable.

It returns true if the thread is joinable or else false.

#include <iostream>
#include <thread>void foo02() {std::this_thread::sleep_for(std::chrono::seconds(2));
}void test02() {//joinablestd::thread t2;//创建了线程对象std::cout << "before joneable: " << t2.joinable() << std::endl;t2 = std::thread(foo02);//joinable  //实例化std::thread对象时传递了“函数名/可调用对象”std::cout << "after joneable: " << t2.joinable() << std::endl;t2.join();//等待std::cout << "after joining,joinable: " << t2.joinable()<<std::endl;
}int main() {   test02();getchar();return 0;
}

part 5:多线程std :: thread :: get_id

Declaration

下面是std::thread::get_id函数的声明。 Following is the declaration for std::thread::get_id function.

id get_id() const noexcept;

C++11

id get_id() const noexcept;

Return Value:It returns the thread id.

Exceptions:No-throw guarantee − never throws exceptions.

Data races:he object is accessed.

#include <iostream>
#include <thread>
#include <chrono>void foo() {std::this_thread::sleep_for(std::chrono::seconds(1));
}int main() {std::thread sample(foo);std::thread::id sample_id = sample.get_id();std::thread sample2(foo);std::thread::id sample2_id = sample2.get_id();std::cout << "sample's id: " << sample_id << '\n';std::cout << "sample2's id: " << sample2_id << '\n';sample.join();sample2.join();
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RgA6jWST-1609517496473)(C:\Users\guoqi\AppData\Roaming\Typora\typora-user-images\1609344040208.png)]

part 6:native_handle 返回底层实现定义的线程句柄

Declaration:Following is the declaration for std::thread::native_handle function.

native_handle_type native_handle();

Return Value:It returns a value of member type thread::native_handle_type.

part 7:hardware_concurrency 返回实现支持的并发线程数

Description

It returns the number of hardware thread contexts.

static unsigned hardware_concurrency() noexcept;

Return Value

It returns the number of hardware thread contexts.

part 8:join 线程执行完成后返回

It returns when the thread execution has completed.

void foo03() {std::this_thread::sleep_for(std::chrono::seconds(2));
}
void bar03() {std::this_thread::sleep_for(std::chrono::seconds(2));
}
void test03() {//join 线程执行完成后返回//It returns when the thread execution has completed.std::cout << " starting helping ...." << std::endl;std::thread helper3(foo02);std::cout << " starting another helping ...." << std::endl;std::thread helper3_2(bar03);std::cout << " waiting for helpers finish...." << std::endl;helper3.join();//线程执行完成后返回helper3_2.join();std::cout << "  done!" << std::endl;
}int main() {test03();getchar();return 0;
}

part 9:detach 容许线程从线程句柄独立开来执行

Description

It returns when the thread execution has completed.

#include <iostream>
#include <chrono>
#include <thread>void independentThread() {std::cout << "Starting thread.\n";std::this_thread::sleep_for(std::chrono::seconds(2));std::cout << "Exiting previous thread.\n";
}void threadCaller() {std::cout << "Starting thread caller.\n";std::thread t(independentThread);t.detach();std::this_thread::sleep_for(std::chrono::seconds(1));std::cout << "Exiting thread caller.\n";
}int main() {threadCaller();std::this_thread::sleep_for(std::chrono::seconds(5));
}

part 10:swap 交换二个 thread 对象

Description

It swaps the state of the object with that of x.

Declaration

Following is the declaration for std::thread::swap function.

void swap (thread& x) noexcept;

part 11:std::swap 特化 std::swap 算法

Description

It is used to exchanges the state of the thread objects x and y.

Declaration

Following is the declaration for std::thread::swap function.

void swap (thread& x, thread& y) noexcept;

Parameters

x,y − It is a thread objects.

实例:

//thread1.cpp  创建线程,并观察线程的并发执行与阻塞等待#include <iostream>
#include <thread>
#include <chrono>using namespace std;void thread_function(int n)
{std::thread::id this_id = std::this_thread::get_id();         //获取线程IDfor(int i = 0; i < 5; i++){    cout << "Child function thread " << this_id<< " running : " << i+1 << endl;std::this_thread::sleep_for(std::chrono::seconds(n));    //进程睡眠n秒}
}class Thread_functor
{
public:// functor行为类似函数,C++中的仿函数是通过在类中重载()运算符实现,使你可以像使用函数一样来创建类的对象void operator()(int n){std::thread::id this_id = std::this_thread::get_id();for(int i = 0; i < 5; i++){cout << "Child functor thread " << this_id << " running: " << i+1 << endl;std::this_thread::sleep_for(std::chrono::seconds(n));   //进程睡眠n秒}}
};int main()
{thread mythread1(thread_function, 1);      // 传递初始函数作为线程的参数if(mythread1.joinable()) //判断是否可以成功使用join()或者detach(),返回true则可以,false则不可mythread1.join();                     // 使用join()函数阻塞主线程直至子线程执行完毕Thread_functor thread_functor;            //函数对象实例化一个对象thread mythread2(thread_functor, 3);     // 传递初始函数作为线程的参数if(mythread2.joinable())mythread2.detach();  // 使用detach()函数让子线程和主线程并行运行,主线程也不再等待子线程//lambda表达式格式:[capture list] (params list) mutable exception-> return type { function body }auto thread_lambda = [](int n){            std::thread::id this_id = std::this_thread::get_id();for(int i = 0; i < 5; i++){cout << "Child lambda thread " << this_id << " running: " << i+1 << endl;std::this_thread::sleep_for(std::chrono::seconds(n));   //进程睡眠n秒}       };thread mythread3(thread_lambda, 4);     // 传递初始函数作为线程的参数if(mythread3.joinable())mythread3.join();                     // 使用join()函数阻塞主线程直至子线程执行完毕std::thread::id this_id = std::this_thread::get_id();for(int i = 0; i < 5; i++){cout << "Main thread " << this_id << " running: " << i+1 << endl;std::this_thread::sleep_for(std::chrono::seconds(1));}getchar();return 0;
}

线程创建的参数是函数对象,函数对象不止是函数指针成员函数指针,同时还包括函数对象(仿函数)与lambda表达式。上面的代码分别用三种函数对象创建了三个线程**,其中第一个线程mythread1阻塞等待其执行完后继续往下执行**,第二个线程mythread2不阻塞等待在后台与后面的第三个线程mythread3并发执行,第三个线程继续阻塞等待其完成后再继续往下执行主线程任务。

为了便于观察并发过程,对三个线程均用了睡眠延时this_thread::sleep_for(duration)函数,且延时时间作为参数传递给该函数。这里的参数是支持C++泛型模板的,STL标准容器类型(比如Array/Vector/Deque/List/Set/Map/String等)都可以作为参数传递,但这里的参数默认是以拷贝的方式传递参数的,当期望传入一个引用时,要使用std::ref进行转换,实例见part 1中实例。

如果想要线程mythread2独立运行,修改如下

mythread2.detach(); ---》   mythread2.join();


线程mythread2和线程mythread3与主线程main 同步运行

mythread2.detach(); ---》   mythread2.join();
mythread3.join();   ---》   mythread3.detach();

小结:

当线程不需要相互依赖,不会产生数据竞争,或不是流水的实现思路下,用detach();

当可能产生数据竞争,数据之间相互依赖,算法实现设计为流水的情况下,使用join()函数,使其他线程进入阻塞状态。

针对任何线程(包括主线程),< thread > 还声明了一个命名空间std::this_thread,用以提高线程专属的全局函数。函数声明和效果见下表。 上面的代码就是利用了std::this_thread提供的函数获得当前线程的ID,让当前线程睡眠一段时间(一般需要< chrono >头文件提供duration或timepoint)的功能 。

参考资料:
https://zh.cppreference.com/w/cpp/thread/thread
https://www.tutorialspoint.com/cpp_standard_library
https://blog.csdn.net/m0_37621078/article/details/104909834

【C++】多线程与并发【一】相关推荐

  1. JAVA多线程和并发基础面试问答

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在 ...

  2. linux线程池实现多线程并发,基于Linux的多线程池并发Web服务器设计-电子设计工程.PDF...

    基于Linux的多线程池并发Web服务器设计-电子设计工程.PDF 第 卷 第 期 电子设计工程 年 月 基于 的多线程池并发 服务器设计 陈 涛 任海兰 武汉邮电科学研究院 湖北 武汉 摘要 时至今 ...

  3. ***JAVA多线程和并发基础面试问答

    多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题.(校对注:非常赞同这个观 ...

  4. 进程、线程、多线程、并发、并行学习记录

    首先,并行与并发都是程序多线程处理场景,因此,一旦提到并行与并发,那首先想到的是多线程. 1,进程 狭义理解就是操作系统中一段程序的执行过程.那么广义上,进程是指一个具有一定独立功能的程序操作系统中关 ...

  5. 多线程高并发 底层锁机制与优化的最佳实践——各种锁的分类 || synchronized 关键字 倒底锁的是什么东西?|| CAS与ABA问题||锁优化||轻量级锁一定比重量级锁的性能高吗

    多线程高并发 底层锁机制与优化的最佳实践 各种锁的分类 加上synchronized 关键字,共享资源就不会出错 synchronized 关键字 倒底锁的是什么东西? synchronized 锁的 ...

  6. Qt多线程示例--并发数据处理

    在通信中,往往会遇到这样的情况 当接入N个子结点,每个子结点向它的父结点发数据,父节点来并发处理总子结点汇集的数据. 对于上述情况,我们经常设计成多线程来并发接收数据,将数据接收后排队存入一个全局变量 ...

  7. java 多线程并发 问题_JAVA多线程和并发基础面试问答

    原文链接 译文连接作者:Pankaj  译者:郑旭东  校对:方腾飞 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌 ...

  8. 【多线程高并发】深入理解JMM产生的三大问题【原子性、可见性、有序性】

    [多线程&高并发]深入浅出原子性 https://blog.csdn.net/Kevinnsm/article/details/121681785?spm=1001.2014.3001.550 ...

  9. 【多线程高并发】深入浅出可见性

    [多线程&高并发]深入浅出原子性 https://blog.csdn.net/Kevinnsm/article/details/121681785?spm=1001.2014.3001.550 ...

  10. 利用curl 多线程 模拟 并发的详解

    来源:http://www.jb51.net/article/38492.htm 首先,先了解下 php中的curl多线程函数: 复制代码代码如下: # curl_multi_add_handle # ...

最新文章

  1. 7纳米duv和euv_要超车台积电 三星宣布采用EUV技术7纳米制程完成验证
  2. 据说只有程序员才看得懂 | 每日趣闻
  3. Maven配置将war包部署到Tomcat(tomcat7-maven-plugin)
  4. Linux总线驱动-02: struct bus_type 结构体
  5. android仿高德地图透明黑字,Android 仿高德地图可拉伸的BottomSheet
  6. Java - 常用工具类 - 集合框架
  7. [译]机器人操作系统简介:终极机器人应用框架(上)
  8. TCP/IP 第三章
  9. Apache配置虚拟主机后,不能访问localhost的问题
  10. 多媒体互动项目-Unity与继电器数据交互
  11. 单片机原理与c语言程序设计付先成版答案,单片机原理与C语言程序设计
  12. 论合同管理的现状、发展趋势及重要性
  13. 谷歌插件学习必备准备知识代码提示插件调试
  14. 全民战疫,我们在行动!
  15. 帝国织梦和各种php网页将局部广告进行屏蔽搜索引擎蜘蛛
  16. 看房一次就租下的90后,大概都喜欢Q房网
  17. IndexedDB踩坑必须注意点!!!
  18. Ubuntu 命令行安装chrome
  19. the king of fighter
  20. 将yuv图像转为.jpg文件

热门文章

  1. python画图程序飞机_Python海龟画图工具绘制叮当猫程序
  2. java 字符处理_Java字符串处理实用代码
  3. 国内 Java 开发者必备的两个神器:Maven国内镜像和Spring国内脚手架
  4. Java面试之Java基础下册(含答案)
  5. 4层板到12层板叠层经典设计方案
  6. opencv感兴趣区域ROI的图像混合操作
  7. 深度学习、AI构图、智能裁图、显著性检测、美感质量评价
  8. mysql从当前月向前推12_JavaScript获取当前时间向前推三个月的方法示例
  9. 机器学习与高维信息检索 - Note 6 - 核, 核方法与核函数(Kernels and the Kernel Trick)
  10. 利用urllib2实现http post请求源码示例