c++并发编程实战-第1章 c++并发世界
前言
c++11开始支持多线程,使得编写c++多线程程序无需依赖特定的平台,使开发者能够编写可移植的、行为确定的多线程程序代码。
什么是并发
所谓并发,是两个或多个同时独立进行的活动。而计算机中的并发,是指同一个系统中,多个独立活动同时进行。
对于单核处理器,在同一时刻,只能处理一个任务,操作系统将一个时刻分成若干时间片,在每个时间片上执行一个任务,从而实现“伪并发”。对于多核处理器,从硬件上支持并发,在同一时刻内能够运行多个任务,我们称之为硬件并发。
并发的方式:多进程并发、多线程并发。
多进程并发
将一个应用软件拆分成多个独立进程同时运行,这些独立进程都只包含一个主线程。这些独立的进程可以通过操作系统提供的API事件进程间通信(套接字、管道、文件、剪切板)。
优点:相互独立,数据资源互不受影响,容易编写出安全的并发代码。
缺点:开销大,需要为每个进程分配资源;进程间通信速度慢,操作复杂。
多线程并发
多线程并发是指在单一进程中运行多个线程,每个线程独立运行,线程间通过共用相同的地址空间,从而实现在线程间通信。
优点:开销低
缺点:操作复杂
并发与并行
并发:主要关心的是分离关注点或响应能力。
并行:主要关心的是利用可调配的硬件资源提升大规模数据处理的性能。
为什么需要使用并发
使用并发的主要原因有:分离关注点、提升性能。
分离关注点
编写软件时,分离关注点几乎总是不错的构思:归类相关代码,隔离无关代码,使程序更易于理解和测试,因此所含缺陷很可能更少。可以将一个应用软件划分成如下几个线程:一个UI线程、一个网络线程、一个数据库读写。各个线程之间相互独立,数据访问通过开放接口实现,从而实现各模块代码各自管理。
提升性能
增强性能的并发方式有两种:
- 第一种是将单一任务分解成多个部分,各自并行运作,从而节省总运行耗时。
- 第二种是利用并行资源解决规模更大的问题。例如,只要条件适合,便同时处理2个文件,或者10个,甚至20个,而不是每次1个。同时对多组数据执行一样的操作,实际上是采用了数据并行,其着眼点有别于任务并行。采用这种方式处理单一数据所需的时间依旧不变,而同等时间内能处理的数据相对更多。
何时避免使用并发
收益不及代价。多数情况下,采用了并发技术的代码更难理解,编写和维护多线程代码会更劳心费神,并且复杂度增加可能导致更多错误。编写正确运行的多线程代码需要额外的开发时间和相关维护成本,除非潜在的性能提升或分离关注点而提高的清晰度值得这些开销,否则别使用并发技术。
并发与C++多线程
早年C++并不支持多线程,程序员若想使用多线程,必须使用平台提供的API,缺点是依赖特定平台,不便跨平台开发;二是可能依赖特定的处理器架构。
c++11开始支持多线程,规定了内存模型,提供多线程操作,线程管控、保护共享数据,线程间同步以及底层原子操作功能。使得开发者摆脱了平台依赖,仅用C++即可写出高效的代码。
若要实现某项功能,代码可以借助高级工具,或者直接使用底层工具。两种方式的运行开销不同,该项差异叫作抽象损失。在绝大数主流平台,C++多线程是低抽象损失。如果开发者追求极致性能,C++也专门提供了相关接口,开发者可以自行开发出高效的多线程程序。通常不建议。
实例
1 #include <iostream>
2 #include <thread>
3
4 void hello()
5 {
6 std::cout << "Son Thread " << std::this_thread::get_id() << std::endl;
7 std::cout << "Hello World!\n";
8 }
9
10 int main()
11 {
12 std::cout << "Main Thread " << std::this_thread::get_id() << std::endl;
13 std::thread th(hello);
14 th.join();
15 }
程序第2行引入头文件<thread>,要使用多线程必须包含该头文件。
在main()函数中,std::this_thread是一个命名空间,在该命名空间中包含获取当前线程相关信息的接口,程序中用get_id()函数获取当前线程的线程ID,用做区分。
要启动一个线程,需要定义一个std::thread对象,该对象需要传递一个可调用对象,作为线程的起始函数,hello()函数就是th线程对象的起始函数。
join()函数的作用的等待子线程执行完毕,主函数会阻塞在此处等待子线程结束。如果不调用join()函数,程序将出现异常情况。
hello()函数是线程的入口函数,线程启动后,最先执行的函数就是hello()函数。
Copyright
本文参考至《c++并发编程实战》 第二版,作者:安东尼·威廉姆斯。本人阅读后添加了自己的理解并整理,方便后续查找,可能存在错误,欢迎大家指正,感谢!
c++并发编程实战-第1章 c++并发世界的更多相关文章
- [书籍翻译] 《JavaScript并发编程》第七章 抽取并发逻辑
本文是我翻译<JavaScript Concurrency>书籍的第七章 抽取并发逻辑,该书主要以Promises.Generator.Web workers等技术来讲解JavaScrip ...
- 那些年读过的书《Java并发编程实战》和《Java并发编程的艺术》三、任务执行框架—Executor框架小结
<Java并发编程实战>和<Java并发编程的艺术> Executor框架小结 1.在线程中如何执行任务 (1)任务执行目标: 在正常负载情况下,服务器应用 ...
- Java并发编程实战---第六章:任务执行
废话开篇 今天开始学习Java并发编程实战,很多大牛都推荐,所以为了能在并发编程的道路上留下点书本上的知识,所以也就有了这篇博文.今天主要学习的是任务执行章节,主要讲了任务执行定义.Executor. ...
- Java并发编程实战 第8章 线程池的使用
合理的控制线程池的大小: 下面内容来自网络.不过跟作者说的一致.不想自己敲了.留个记录. 要想合理的配置线程池的大小,首先得分析任务的特性,可以从以下几个角度分析: 任务的性质:CPU密集型任务.IO ...
- [笔记][Java7并发编程实战手冊]3.8 并发任务间的数据交换Exchanger
[笔记][Java7并发编程实战手冊]系列文件夹 简单介绍 Exchanger 是一个同步辅助类.用于两个并发线程之间在一个同步点进行数据交换. 同意两个线程在某一个点进行数据交换. 本章exchan ...
- 【java并发编程实战】第一章笔记
1.线程安全的定义 当多个线程访问某个类时,不管允许环境采用何种调度方式或者这些线程如何交替执行,这个类都能表现出正确的行为 如果一个类既不包含任何域,也不包含任何对其他类中域的引用.则它一定是无状态 ...
- Java并发编程实战 第16章 Java内存模型
什么是内存模型 JMM(Java内存模型)规定了JVM必须遵循一组最小保证,这组保证规定了对变量的写入操作在何时将对其他线程可见. JMM为程序中所有的操作定义了一个偏序关系,称为Happens-Be ...
- Java并发编程实战 第5章 构建基础模块
同步容器类 Vector和HashTable和Collections.synchronizedXXX 都是使用监视器模式实现的. 暂且不考虑性能问题,使用同步容器类要注意: 只能保证单个操作的同步. ...
- JAVA并发编程实战---第三章:对象的共享(2)
线程封闭 如果仅仅在单线程内访问数据,就不需要同步,这种技术被称为线程封闭,它是实现线程安全性的最简单的方式之一.当某个对象封闭在一个线程中时,这种方法将自动实现线程安全性,即使被封闭的对象本生不是线 ...
- 《Java并发编程实战》第九章 图形用户界面应用程序界面 读书笔记
一.为什么GUI是单线程化 传统的GUI应用程序通常都是单线程的. 1. 在代码的各个位置都须要调用poll方法来获得输入事件(这样的方式将给代码带来极大的混乱) 2. 通过一个"主事件循环 ...
随机推荐
- 天线的OTA测试
有源测试 (即OTA测试) 把使用综测仪的测试叫做有源测试(Active).使用有源测试的测试速度比较无源相对要慢,但是因为手机是一个复杂材料体,往往无源测试对发射性能的模拟是可信的,但是对于接收性能 ...
- 反范式设计,冗余用户姓名,修改用户姓名后,业务表同步更新 -- MySQL 存储过程
反范式设计,冗余用户姓名,通过存储过程进行业务表的同步更新. 所有的表,在创建的时候,都加了创建人.修改人的字段..用户姓名发生变化时,要将所有的表都更新一遍. 创建存储过程 MySQL CREATE ...
- el-table 数据嵌套循环
<el-table :data="tableData" :show-header="false" style="width: ...
- Thymeleaf Split
<th:block th:each="image : ${#strings.listSplit(goods.images, ';')}"> <img th:src ...
- 纯离线部署本地知识库LLM大模型
纯离线部署本地知识库LLM大模型 一.下载离线大模型 下载的网址:https://hf-mirror.com/ deepseek qwen 相关的模型,只建议使用1.5B的,GGUF后缀的模型 推荐下 ...
- Python基础--python数据结构(字符串、列表和元组)
前言 !!!注意:本系列所写的文章全部是学习笔记,来自于观看视频的笔记记录,防止丢失.观看的视频笔记来自于:哔哩哔哩武沛齐老师的视频:2022 Python的web开发(完整版) 入门全套教程,零基础 ...
- go map fatal error: concurrent map iteration and map write 读写锁与深度拷贝的坑
起因 从币安实时拉取交易对的数据,这里使用了 map,用于存放每个交易对的最新价格,由于 map 并不是并发安全的所以加了读写锁. 但系统有时候还是会发生 fatal error: concurren ...
- 搭建自己的OCR服务,第三步:PPOCRLabel标注工具安装
一.安装说明 安装好了PaddleOCR后,还需要安装PPOCRLabel这个标注工具,想要自己训练模型的话,有个标注工具会起很大作用. 尤其是PPOCRLabel就是跟PaddleOCR配套的标注工 ...
- DCL(Double-checked Locking双重校验锁)实现单例模式的原理、问题与解决方案
好的,要深入理解DCL(Double-Checked Locking)双重校验锁的原理.问题以及解决方法. 首先,我需要回忆一下单例模式的基本概念,因为DCL通常用于实现单例模式. 单例模式确保一 ...
- GPU CPU运算时间测试
GPU CPU运算时间测试 本文主要探讨GPU,CPU在做一些复杂运算的时间测试 实验任务 1.向量加法 两个相同维度的向量a,b做加法,分别测试GPU并行时间(包含数据拷贝时间),CPU串行时间. ...