Chapter_1 你好,C++的并发世界

并发是指系统同时执行多个独立任务的能力。这可通过多进程或多线程实现,前者提供更高级别的保护和通信机制,但开销大,后者共享地址空间,效率高但需要管理数据一致性。并发的主要原因是提高性能和分离关注点,但需权衡成本。C++从C++11开始支持多线程编程。
摘要由CSDN通过智能技术生成

何谓并发(concurrency)?

计算机中的并发是指单个系统在同时执行多个独立的任务。

当计算机只有一个处理器的时候,具有单个处理单元(processing uint)或者核心(core),这种机器在处理多任务的时候是在不停地进行任务切换(task switching),这样仍然可以称之为并发。

现在有了单芯多核的计算机可以真正的并行处理多个任务,我们称之为硬件并发(hardware concurrency)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fT8Yn1o7-1646023114780)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/aa3e3845-5af8-439a-93b2-72658ee05cef/Screen_Shot_2022-02-27_at_21.48.44.png)]

有些处理器可以在一个核心上执行多个线程,但是硬件并发在多处理器或者多核系统上的效果更加显著。硬件线程(hardware threads)最重要的因素是数量,也就是硬件上可以并发运行多少独立的任务

并发的途径

方法一:多进程并发

将应用程序分为多个独立的进程,在同一时刻运行,独立的进程之间可以通过常规的信息渠道传递讯息。

缺点:进程之间的通信通常设置复杂,速度慢(因为OS会在进程间设置保护措施,避免一个进程回去修改另一个进程),还有一个缺点就是运行多个进程所需的固定开销:需要时间启动进程,操作系统需要内部资源来管理进程。

优点:OS在进程见提供的附加保护操作和更高级别的通信机制,意味着可以编写更加safe的并发代码。另外一个有时就是可以使用远程连接的方式,在不同的机器上运行独立的进程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ptxhWEEj-1646023114781)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/f51d92c8-2fed-4e12-9621-8333c41c5d37/Screen_Shot_2022-02-28_at_10.18.30.png)]

方法二:多线程并发

在单个进程中运行多个线程,每个线程之间相互独立,可以在不同的指令序列中运行。

缺点:进程中所有线程都共享地址空间,所欧线程访问到大部分数据,全局变量仍然是全聚德,指针、对象的引用或者数据都可以在线程之间传递。虽然进程之间也能共享内存,但是这种贡献通常是难以建立的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lTcin8a0-1646023114781)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/34506210-bd20-4611-a916-be0964f0081d/Screen_Shot_2022-02-28_at_10.25.13.png)]

地址空间的共享,以及缺少线程之间的数据保护,使得OS的工作量变小,开销就比多进程小的多,但是这些优点都是有代价的:如果数据要被多个线程访问,程序员就要保证每个线程所访问到的数据是一致的

为什么并发

为了分离关注点

将相关代码和无关代码进行分离,使程序可以能加容易理解和测试

为了性能

1⃣️:单个任务分成几个部分,并且各自并行运行,降低总运行时间:任务并行(task parallelism)

2⃣️:每个线程在 不同的数据部分上执行相同的操作:数据并行(data parallelism)

什么时候不能并发

收益比不上成本:除非潜在的性能增益足够 大或关注点分离地足够清晰,能抵消所需的额外的开发时间以及与维护多线程代码相关的额 外成本(代码正确的前提下);否则,别用并发。

C++中使用的并发和多线程

C++11开始编写不以来平台拓展的多线程代码

历史

c++98不承认线程的存在

开始入门

#include <iostream>
// 多线程头文件,管理线程的函数和类声明在<thread>中,
// 保护共享数据的函数和类在其他头文件中声明
#include <thread>

using namespace std;

// 写信息的代码被移动到了一个独立的函数中,因为每个线程必须具有一个初始函数
// 新线程的执行在这里开始,对于应用程序来说,初始线程是main(),对于替他线程,可以在std::thread中指定
// 在本例中,命名为t的thread对象拥有函数hello()作为其初始函数
void hello(){
    cout << "hello mutlithread world" <<endl;
}
// 与直接写入标准输出或是从main()调用hello()不同,
// 该程序启动了一个全新的线程来实现,将线程数量一分为二——初始线程始于main(),而新线程始于hello()。
int main(){
    // 新线程启动后,初始线程继续执行初始线程继续执行。如果它不等待新线程结束,
    // 它就将自顾自地继续运行到main()的结束,从而结束程序——有可能发生在新线程运行之前,
    // 所以会用到 join()
    std::thread t(hello);
    t.join();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值