关于高并发场景和进程线程协程的一些总结

news/2024/4/26 0:13:45/文章来源:https://blog.csdn.net/weixin_53344209/article/details/129193783

1、IO复用和线程池哪个好?应用场景?

IO复用就是一个线程处理多个客户端连接。如果自己实现的话,就是要不断轮询每个客户端连接,看看有没有事件发生(数据到达),即使可以用非阻塞的read函数,但是也会花很多时间在CPU空转上,因为可能数据都没到达,就白轮询了。
而系统提供了这种机制,select等模型,让操作系统来实现,只要有一个可读事件就返回(或者超时返回),然后进行处理(至于底层的原理数据结构,看面经积累那篇文章)。至于处理是单线程,还是一个线程处理一个连接(这其实就是reactor模型),具体就看业务场景了。
IO复用适合的场景就是:
1、处理过程简单,因为创建切换线程是需要时间的,如果很简单,一个熟练工自己做就可以,分发给很多人做需要时间,可能分发的时间代价比自己做好这一个连接请求还大。如果处理过程复杂一点,代价比创建切换线程时间大,那么可以多线程。如果完全是一个计算密集的任务,IO消耗可忽略,多进程充分利用CPU核数的计算力更重要,多线程的重要目的就是在IO阻塞时挂起线程让CPU执行别的任务,充分利用CPU,不让他闲置。计算密集型任务基本上就没有IO阻塞这一说,CPU一直是满负载的。并且相对来说,进程更加健壮,进程之间不影响,而线程之间会互相影响,因为是公用内存空间的。
2.适合长连接,有很多闲置IO的场景。因为如果为每个IO设置一个线程,将会大大增加内存消耗,线程创建需要空间(10M左右)。
3.上层应用编程方便。因为多线程会有线程安全,并发编程问题,需要加锁等机制。方便也是一大因素,不然就不会有python这种方便但是性能不够好的语言了。因为可以实现需求比为了性能实现不了需求要好。

比如redis,nigix就是典型的IO复用,单线程的。
nigix反向代理的转发逻辑简单,所以是单线程的。redis因为是基于内存的,CPU不是瓶颈(也就是说逻辑处理很快,相对就是简单),瓶颈可能是网络带宽等,一个CPU完全有足够的算力去实现所有客户端连接的请求处理,单个的请求处理过程很快,不需要让客户端等待很久,反而是创建切换线程会让客户端等的更久。如果并发量特别大,希望充分利用其他的CPU,就可以多开几个redis进程。
redis为什么快
(基于内存,数据用哈希表存储,内存的读写速度非常快,查找和操作的时间复杂度都是O(1))
(redis是单线程的,省去了很多上下文切换线程的时间(避免线程切换和竞态消耗))
(redis使用IO多路复用技术(IO multiplexing, 解决对多个I/O监听时,一个I/O阻塞影响其他I/O的问题),可以处理并发的连接(非阻塞IO))

2、IO复用模型用的是非阻塞IO吗? 阻塞非阻塞,同步异步IO的区别?
首先阻塞IO是什么流程?
在这里插入图片描述
在读的时候,如果没有数据,就一直阻塞等待,这是第一部分,有数据后,将数据从内核复制到用户空间(定义的buffer中),这是第二部分。然后read才完成;
非阻塞IO
在这里插入图片描述
读调用时,如果没有数据,就直接返回错误,不需要阻塞等待,准备好后就拷贝数据到缓冲区。

可以发现,阻塞非阻塞第二步相同,都得等到数据拷贝完成才返回处理数据,因此它们都是同步IO。而异步IO就是第二步拷贝不需要等待完成就直接返回进行下面的代码,拷贝完成后会有信号通知即回调函数完成操作。

那么IO复用是不是阻塞呢?
首先,IO复用在操作系统层面应该是不阻塞的,在应用层面阻塞。首先select函数返回必须有一个可读事件发生,没有的话是会阻塞的,但这是编程层面的,可以通过超时时间来控制。返回后遍历fdset,这时的read调用就是非阻塞的,没有数据直接返回错误,有数据就拷贝到缓冲区,并处理。

4、多线程为什么能提高并发度?和CPU核数的关系?单核跑多线程有意义吗?
多线程,多进程在单核跑有意义吗?我们要了解多线程的应用场景。
多线程主要用于有很多IO操作的地方,比如磁盘IO,网络IO。IO操作时不需要占用cpu时间的,一个cpu同一时刻只能被一个线程占用。当一个线程在IO操作被阻塞时,完全可以让出CPU,让需要CPU的线程执行。所以意义就是错开IO和cpu的使用。一个线程是串行处理所有操作,一个客户端处理完再处理下一个,有IO时CPU就空闲等待。而多线程的话,一个客户端处于IO时,CPU就让另一个需要IO的客户端执行,这样CPU利用率变高了,每个客户端处理的速度也变快了。但是如果计算密集的话,没有IO时间,就不需要多线程。
有多个CPU时,多线程就更加能发挥作用了,充分利用多个CPU的处理能力。现在的处理器一般都是好多CPU核心的。

所以个人经验:如果逻辑处理很简单,就用IO复用+单线程;如果逻辑处理稍微复杂,大于创建切换线程的时间,就用IO复用+多线程(线程池);如果完全是计算密集的任务,就看几个CPU核心,开几个进程,基本不需要调度进程。

5、系统调用(用户内核态切换)、切换线程,协程,进程到底要多少时间?做了什么事情?
首先,系统调用做的是就是进程内将用户态切换到内核态,然后再切回来。大概是ns级别,开销比较小;并且进程线程切换都得经过用户态到内核态的转换。
进程切换大概是3.5us,毫秒级别,开销较大。(实验方法是创建两个进程并在它们之间传送一个令牌。其中一个进程在读取令牌时就会引起阻塞。另一个进程发送令牌后等待其返回时也处于阻塞状态。如此往返传送一定的次数,然后统计他们的平均单次切换时间开销。)
这些开销主要分成两部分:直接开销:PCB的修改,调度器的执行,全局页表目录的修改,硬件上下文(返回地址等)
间接开销:虽然切换到一个新进程后,由于各种缓存并不热,速度运行会慢一些。如果进程始终都在一个CPU上调度还好一些,如果跨CPU的话,之前热起来的TLB、L1、L2、L3因为运行的进程已经变了,所以以局部性原理cache起来的代码、数据也都没有用了,导致新进程穿透到内存的IO会变多。

线程开销较小,因为共享进程的虚拟地址空间,没有页表的切换,TLB命中率降低等因素。只要切换自己的栈和程序计数器PC即可。也是毫秒级别。

为了实现异步,通常会用回调函数,这样可以尽量避免线程切换的开销。但是这么做不是人类正常的思维,代码维护困难。最好可以用同步的代码写出异步的效果,协程可以做到。协程在应用层又动起了主意,设计出了不需要进程/线程上下文切换的“线程”,协程。用协程去处理高并发的应用场景,既能够符合进程涉及的初衷,让开发者们用人类正常的线性的思维去处理自己的业务,也同样能够省去昂贵的进程/线程上下文切换的开销
协程开销大概是120ns,甚至比系统调用还快。并且协程的内存占用只有KB级别,也很小。

协程缺点就是,需要程序员自己执行切换时机,不像进程线程,操作系统会完成这些步骤。操作系统的一个主要设计目标是实时性,对优先级比较高的进程是会抢占当前占用CPU的进程。但是协程无法实现这一点,还得依赖于使用CPU的一方主动释放,与操作系统的实现目的不相吻合。协程的高效是以牺牲了可抢占性为代价的。所以协程的调度设计很重要。
另外,协程的栈空间太小了,一旦比较复杂的业务,很有可能会溢出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_73562.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python编写GUI界面,实现小说下载器

嗨害大家好鸭&#xff01;我是小熊猫~思路一、数据来源分析二. 代码实现步骤代码实现一、单章小说下载二、整本小说下载三、多线程采集四、采集排行榜所有小说五、搜索小说功能六、GUI界面<center>**&#x1f447;问题解答 源码获取 技术交流 抱团学习请联系&#x1f…

金仓数据库安装

一、麒麟操作系统安装金仓数据库 操作系统 DISTRIB_IDKylin DISTRIB_RELEASEV10 DISTRIB_CODENAMEjuniper 按照安装文档的步骤安装&#xff0c;记得记住设置的数据库的用户名、密码 二、window安装连接数据库的工具软件 三、jdbc连接数据库 &#xff08;1&#xff09;连接工…

错误记录:py2neo.errors.ProtocolError: Cannot decode response content as JSON

py2neo.errors.ProtocolError: Cannot decode response content as JSON 原因&#xff1a;目前不清楚 解决方法&#xff1a;进入\lib\site-packages\py2neo\database.py中更改graph_name为neo4j 程序正常运行

Linux命令及CPU占用过高的定位分析思路

一、vim命令不要使用vim打开大文件&#xff0c;vim会一次性读取所有内容到内存&#xff0c;容易造成宿主机内存溢出。 打开文件前&#xff0c;可以使用du -h命令查看文件大小。一般&#xff0c;100MB以下为宜。1、普通模式j 向下30j 向下移动30行k 向上h 向左l 向右0 到行首^ 到…

分阶段构建golang运行环境Dockerfile镜像

在开始这项工作之前大家可以先去看一下docker官方给出关于空镜像scratch的说明&#xff0c;采用官方简单的一句话就是&#xff1a;scratch是一个明确的空图像&#xff0c;特别是对于“从头开始”构建图像。分阶段构建镜像就会用到scratch这个空镜像&#xff0c;这样的好处是可以…

Vulnhub靶场----7、DC-7

文章目录一、环境搭建二、渗透流程三、思路总结一、环境搭建 DC-7下载地址&#xff1a;https://download.vulnhub.com/dc/DC-7.zip kali&#xff1a;192.168.144.148 DC-7&#xff1a;192.168.144.155 二、渗透流程 nmap -T5 -A -p- -sV -sT 192.168.144.155思路&#xff1a; …

【Rust 日报】2023-2-23 Ambient 0.1 发布

治理改革 RFC公告官方博客发布了治理改革RFC的公告&#xff0c;了解详情请点开链接查看。主要看点其实是新的RFC改革治理之后&#xff0c;提供了多语言的支持&#xff0c;其中包括简体中文&#xff0c;该PR目前还在讨论中。原文: https://blog.rust-lang.org/inside-rust/2023/…

RabbitMQ 实现延迟队列

业务场景&#xff1a;1.生成订单30分钟未支付&#xff0c;则自动取消&#xff0c;我们该怎么实现呢&#xff1f;2.生成订单60秒后,给用户发短信1 安装rabbitMqwindows安装ubuntu中安装2 添加maven依赖<!-- https://mvnrepository.com/artifact/org.springframework.boot/spr…

「JVM 编译优化」Graal 编译器

文章目录1. 历史背景2. 构建编译调试环境3. JVMCI 编译器接口4. 代码中间表示5. 代码优化与生成1. 历史背景 Graal 编译器在 JDK 9 以 Jaotc 提前编译工具的形式首次加入到官方的 JDK 中&#xff0c;JDK 10 开始提供替换&#xff08;得益于 HotSpot 编译器接口&#xff0c;Jav…

扬帆优配|“涨停敢死队”慌了?监管“盯紧”异常交易

日前&#xff0c;沪深买卖所发布《主板股票反常买卖实时监控细则》&#xff0c;对反常买卖行为的类型和标准作出规则。其间&#xff0c;针对“打板”“封板”等反常行为的监控遭到商场重视&#xff0c;有商场传闻称&#xff0c;新规或导致高频买卖毁灭&#xff0c;“量价型股票…

MySQL进阶知识

1 存储引擎1.1 MySQL体系结构1.2 存储引擎简介存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式。存储引擎是基于表的&#xff0c;而不是基于库的&#xff0c;同一个库的多个表可以采用不同的存储引擎&#xff0c;所以存储引擎也经常称为表类型。创建表时可以指…

pyhon笔记——Anaconda安装

一、简介 Anaconda包括Conda、Python以及一大堆安装好的工具包&#xff0c;比如&#xff1a;numpy、pandas等 Miniconda包括Conda、Python conda是一个开源的包、环境管理器&#xff0c;可以用于在同一个机器上安装不同版本的软件包及其依赖&#xff0c;并能够在不同的环境之…

Android:实现签名功能——signature-pad库

文章目录实现效果步骤1、添加 signature-pad 库的依赖。2、在 layout 文件中使用 SignaturePad 控件&#xff0c;另外添加“清空”和“保存”两个按钮。3、实现清空 SignaturePad 控件内容的功能4、实现保存 SignaturePad 控件内容的功能5、实现兼容Android10以下和Android10以…

Video 标签无法播放 mp4 的原因和解决办法

问题 用 QQ 的截图录屏功能录制的 mp4 视频&#xff0c;无法用 <video> 标签正常播放。 原因 通过搜索的说法是&#xff1a; 查阅文档&#xff08;不知道是啥文档&#xff09;&#xff0c;关于video标签所支持的视频格式和编码&#xff1a; MPEG4 带有H.264视频编码和…

大规模食品图像识别:T-PAMI 2023论文解读

美团基础研发平台视觉智能部与中科院计算所展开科研课题合作&#xff0c;共同构建大规模数据集Food2K&#xff0c;并提出渐进式区域增强网络用于食品图像识别&#xff0c;相关研究成果已发表于T-PAMI 2023。本文主要介绍了数据集特点、方法设计、性能对比&#xff0c;以及基于该…

【STM32MP157应用编程】2.GPIO输入、输出、中断

目录 GPIO文件 指令操作GPIO 程序操作GPIO 程序说明 程序代码 2_GPIO_4.c 启动交叉编译工具 编译 拷贝到开发板 测试 GPIO文件 在/sys/class/gpio目录下&#xff0c;存放了GPIO的文件。 gpiochipX&#xff1a;当前SoC所包含的GPIO控制器&#xff0c;STM32MP157一共包…

input 子系统

简介 先来了解什么是输入设备&#xff1f; 常见的输入设备有键盘、 鼠标、 遥控杆、 书写板、 触摸屏等等,用户通过这些输入设备与 Linux 系统进行数据交换。 什么是输入系统&#xff1f; 输入设备种类繁多&#xff0c; 能否统一它们的接口&#xff1f; 既在驱动层面统一&…

x64dbg和IDA pro 配置PDB 符号文件symbols

PDB 作用 PDB&#xff08;Program Debugging Database&#xff09;就是在生成EXE 和 DLL 文件的过程中生成的这个文件&#xff0c;可以帮助进行调试。 为什么x64dbg 没有将PDB 文件集成到软件中呢&#xff1f;主要是PDB 文件太大了&#xff0c;在分发安装包的时候会很大&#…

数据库浅谈之 DuckDB AGG 底层实现

数据库浅谈之 DuckDB AGG 底层实现 HELLO&#xff0c;各位博友好&#xff0c;我是阿呆 &#x1f648;&#x1f648;&#x1f648; 这里是数据库浅谈系列&#xff0c;收录在专栏 DATABASE 中 &#x1f61c;&#x1f61c;&#x1f61c; 本系列阿呆将记录一些数据库领域相关的知…

小米/红米手机数据恢复:从小米手机恢复已删除的数据

如果您不小心删除了小米手机上的数据&#xff0c;后来发现您需要它&#xff0c;那么本文适合您。我将向您介绍一些最可靠的小米恢复方法&#xff0c;以将您的数据恢复到您的设备上。无论您是否有备份&#xff0c;都可以处理。让我们开始吧&#xff01; 小米数据恢复 - 如何做&a…