python并发编程:阻塞IO

news2024/11/24 15:20:47

阻塞IO(blocking  IO)

在Linux中,默认情况下所有的socket都是blocking,一个典型的读操作流程大概是这样:

  当用户进程调用了recvfrom这个系统调用,kernel就开始了IO的第一个阶段:准备数据。对于network io来说,很多时候数据在一开始还没有到达(比如,还没有收到一个完整的udp包),这个时候kernel就要等待足够的数据到来

1

2

而在用户进程这边,整个进程会被阻塞,当kernel一直等到数据准备好了,它就会将数据从kernel中拷贝到用户内存

然后kernel返回结果,用户进程才解除block的状态,重新运行起来

  所以,blocking IO的特点就是在IO执行的两个阶段(等待数据和拷贝数据两个阶段)都被block了

1

2

3

4

5

6

7

8

9

10

几乎所有的程序员第一次接触到的网络编程都是从listen(),send(),recv()等接口开

始的,使用这些接口可以很方便的构建服务器/客户机的模型。然而大部分的socket接口都是

阻塞型的。如下图

ps:

所谓阻塞型接口是指系统调用(一般是IO接口)不返回调用结果并让当前线程一直阻塞

只有当该系统调用获得结果或者超时出错时才返回。

  

实际上,除非特别指定,几乎所有的IO接口(包括socket接口)都是阻塞型的。这给网络编程带来了一个很大的问题。如在调用recv(1024)的同时,线程将被阻塞,在此期间,线程将无法执行任何运算或响应任何的网络请求。

一个简单的解决方案:

1

在服务端使用多线程(或多进程)。多线程(或多进程)的目的是让每个连接都拥有独立的线程(或进程),这样任何一个连接的阻塞都不会影响其他的连接。

  该方案的问题是:

1

开启多进程或多线程的方式,在遇到同时响应成百上千的连接请求,则无论多线程还是多进程都会严重占据系统资源,降低系统对外界响应效率,而且线程与进程本身也更容易进入假死状态

  改进方案:

1

2

很多程序员可能会考虑使用“线程池”或“连接池”。“线程池”旨在减少创建和销毁线程的频率,其维持一定合理数量的线程,并让空闲的线程重新承担新的执行任务。“连接池”维持连接的缓存池,尽量重用已有的连接,减少创建和关闭连接的频率。这两种技术都可以很好的降低系统开销,都被广泛应用很多

大型系统,如websphere、tomcat和各种数据库等

  改进后方案其实也存在着问题:

1

2

3

“线程池”和“连接池”技术也只是在一定程度上缓解了频繁调用IO接口带来的资源占用。而且“池”始终尤其上限,当请求大大超过上限时,“池”构成的系统对外界的响应并不比没有池

的时候效果好多少。

所以使用“池”必须考虑其面临的响应规模,并根据规模调整“池”的大小

  对应上例中的所面临的可能同时出现的上千甚至上万次的客户端请求,“线程池”或“连接池”或许可以缓解部分压力,但是不能解决所有问题。总之,多线程模型可以方便高效的解决小规模的服务请求,但面对大规模的服务请求,多线程模型也会遇到瓶颈,可以用非阻塞接口来尝试解决这个问题。

练习:

服务端:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

from socket import *

from threading import Thread

def communicate(conn):

    while True:

        try:

            data = conn.recv(1024)

            if not data:

                break

            conn.send(data.upper())

        except ConnectionResetError:

            break

    conn.close()

server = socket(AF_INET, SOCK_STREAM)

server.bind(('127.0.0.1'8080))

server.listen(5)

while True:

    print('starting...')

    conn,addr = server.accept()

    print(addr)

    = Thread(target=communicate, args=(conn,))

    t.start()

server.close()

  客户端:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

from socket import *

client = socket(AF_INET, SOCK_STREAM)

client.connect(('127.0.0.1'8080))

while True:

    msg = input("请输入数据:").strip()

    if not msg:

        continue

    client.send(msg.encode('utf-8'))

    data = client.recv(1024)

    print(data.decode('utf-8'))

client.close()

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

将Remix和本地文件连接

Remix连接本地文件 推荐使用网页版本的Remix,因为它是实时更新的,还可以连接MetaMask直接进行使用。 打开remix网页,可以通过 create a new workspace新建页面 然后找到我们要连接 的文件目录,在该目录中打开终端,如…

Pytorch学习 day05(RandomCrop、Transforms工具使用总结)

RandomCrop 将PIL或Tensor格式的输入图片,随机裁剪指定尺寸的部分输入尺寸可以为序列或单个整形数字代码如下: from PIL import Image from torchvision import transforms from torch.utils.tensorboard import SummaryWriterimg Image.open("i…

通过hyperbeam创建梁单元截面属性

1、为模型中标准的圆柱形创建梁单元和赋予属性; 2、为模型中不标准的对称性实体创建梁单元和赋予属性; 3、为模型中壳体部分创建梁单元和赋予属性;

C++进阶之路---继承(一)

顾得泉:个人主页 个人专栏:《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂,年薪百万! 一、继承的概念及定义 1.继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0…

MybatisPlus入门详解

一、MyBatisPlus 简介 1.1 创建新模块 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.1</version></dependency> 由于mp并未被收录到idea的系统内置配置,无法…

外包干了2年,技术退步明显

先说一下自己的情况&#xff0c;研究生&#xff0c;19年进入广州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&#xf…

Android开发中遇到最难的问题,app架构图

前言 这份Android面试真题涵盖了图片&#xff0c;网络和安全机制&#xff0c;网络&#xff0c;数据库&#xff0c;插件化、模块化、组件化、热修复、增量更新、Gradle&#xff0c;架构设计和设计模式&#xff0c;Android Framework 、Android优秀三方库源码等。适合中高级工程…

Windows安装MySQL详细教程

1.1 下载MySQL压缩包 官网下载链接[点击跳转] 按图中选择&#xff0c;然后点击【Download】 点击图中箭头所指方向直接下载 1.2 解压下载好的压缩包后找到【bin】文件夹&#xff0c;并记下文件路径&#xff08;下文将以路径 D:\mysql-8.0.36-winx64\bin 为例&#xff09; 1.…

JavaScript实现点击鼠标弹钢琴的效果

思路&#xff1a; 图片设置宽900px&#xff0c;找到鼠标按下时的x坐标和img距离body的x坐标&#xff0c;两个值相减&#xff0c;然后除100取整&#xff0c;赋值给a&#xff0c;通过判断a的值来确定放出那个音乐。 完整代码&#xff1a; <!DOCTYPE html> <html lan…

【DAY05 软考中级备考笔记】线性表,栈和队列,串数组矩阵和广义表

线性表&#xff0c;栈和队列&#xff0c;串数组矩阵和广义表 2月28日 – 天气&#xff1a;阴转晴 时隔好几天没有学习了&#xff0c;今天补上。明天发工资&#xff0c;开心&#x1f604; 1. 线性表 1.1 线性表的结构 首先线性表的结构分为物理结构和逻辑结构 物理结构按照实…

python GPU加速 以numba为例

GPU编程(CUDA) GPU(图形处理单元)&#xff0c;多核系统&#xff0c;而现今的大多数CPU也属于多核系统&#xff0c;但它们之间还是存在很大的区别: CPU适合执行复杂的逻辑&#xff0c;比如多分支&#xff0c;其核心比较重(复杂)GPU适合执行简单的逻辑&#xff0c;大量的数据计…

JVM内部世界(内存划分,类加载,垃圾回收)

&#x1f495;"Echo"&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;JVM内部世界(内存划分,类加载,垃圾回收) 关于JVM的学习主要掌握三方面: JVM内存区的划分类加载垃圾回收 一.JVM内存区的划分 当一个Java进程开始执行时,JVM会首先向操作系统申…

给数字人生成加上界面,基于ER-NeRF/RAD-NeRF/AD-NeRF,Gradio框架构建WEBUI,使用HLS流媒体,实现边推理边播放——之一:在WEBUI中实时输出服务器控制台日志

前言 目前数字人实现技术众多&#xff0c;我这里采用基于ER-NeRF&#xff0c;在这里可以看到其介绍&#xff1a;ICCV 2023 | ER-NeRF: 用于合成高保真Talking Portrait的高效区域感知神经辐射场-https://zhuanlan.zhihu.com/p/644520609ER-NeRF的项目地址&#xff1a;https://…

十四、重写与多态

重写、多态 上一讲是&#xff0c;子类对父类横向上的扩展 这一讲是&#xff0c;子类对父类纵向上的扩展 方法重写 使用override关键字重写父类的方法 将父类原本方法的逻辑更新成新版本的逻辑 注&#xff1a;仅能重写可见的父类成员&#xff0c;并且重写要保持签名一致。 签名一…

第五节 JDBC驱动程序类型

JDBC驱动程序是什么&#xff1f; JDBC驱动程序在JDBC API中实现定义的接口&#xff0c;用于与数据库服务器进行交互。 例如&#xff0c;使用JDBC驱动程序&#xff0c;可以通过发送SQL或数据库命令&#xff0c;然后使用Java接收结果来打开数据库连接并与数据库进行交互。 JDK…

Java中常见的 IO 方式

冯诺依曼结构中计算机结构被分为 5 大部分&#xff1a;运算器、控制器、存储器、输入设备、输出设备&#xff0c;输入设备向计算机输入数据&#xff0c;输出设备接收计算机输出的数据。从计算机结构的视角来看的话&#xff0c; I/O 描述了计算机系统与外部设备之间通信的过程。…

JMeter VS RunnerGo :两大主流性能测试工具对比

说起JMeter&#xff0c;估计很多测试人员都耳熟能详。它小巧、开源&#xff0c;还能支持多种协议的接口和性能测试&#xff0c;所以在测试圈儿里很受欢迎&#xff0c;也是测试人员常用的工具&#xff0c;不少企业也基于JMeter建立起自己的自动化测试能力&#xff0c;提升工作效…

体验Node.js的安装和运行

Node.js概述 Node.js是一个基于Chrome V8引擎的JavaScript运行环境。它允许JavaScript代码在服务器端运行&#xff0c;使得开发人员可以使用同一种语言编写前端和后端的代码。Node.js使用事件驱动、非阻塞I/O模型&#xff0c;使其轻量且高效&#xff0c;非常适合数据密集型的实…

java性能调优面试,程序员Java视频

前言 很多人在打算自学Java的时候或许都没有思考过Java的应用方向&#xff0c;市场需要什么样的人才&#xff0c;企业对你有什么要求等等一系列问题&#xff1b;或许你只听说这个行业薪资高…然后懵懵懂懂的上路&#xff0c;不得要害。 对于零基础来学习Java&#xff0c;你或…

怎样才能考上南京大学的计算机研究生?

附上南大与同层次学校近四年的分数线对比&#xff0c;整体很难 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 我本人是双非一本的计算机专业&#xff0c;23考研一战上岸的&#xf…