python 并发编程 阻塞IO模型原理解析


Posted in Python onAugust 20, 2019

阻塞IO(blocking IO)

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

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

等着对方把数据放到自己操作系统内存

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

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

这就是阻塞IO

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

网络编程都是从listen\(\)、send\(\)、recv\(\) 等接口开始的,
使用这些接口可以很方便的构建服务器/客户机的模型。然而大部分的socket接口都是阻塞型的。如下图

ps:

所谓阻塞型接口是指系统调用(一般是IO接口)不返回调用结果并让当前线程一直阻塞
只有当该系统调用获得结果或者超时出错时才返回。

服务端:

from socket import *
server = socket(AF_INET,SOCK_STREAM)
server.bind(('127.0.0.1',8000))
server.listen(5)
while True:
  print("starting...")
  conn,addr = server.accept()
  print(addr)
  while True:
    try:
      data = conn.recv(1024)
      if not data:break
      conn.send(data.upper())
    except ConnectionResetError:
      break
server.close()

客户端

from socket import *
client = socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8000))
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()

python 并发编程 阻塞IO模型原理解析

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

一个简单的解决方案:

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

该方案的问题是 :

开启多进程或都线程的方式,在遇到要同时响应成百上千路的连接请求,则无论多线程还是多进程都会严重占据系统资源,
降低系统对外界响应效率,而且线程与进程本身也更容易进入假死状态。
随着客户端数量增多,无限制的开线程,开销非常大
不能解决阻塞IO问题 ,解决思路:起多线程

改进方案:

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

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

“线程池”和“连接池”技术也只是在一定程度上缓解了频繁调用IO接口带来的资源占用。而且,所谓“池”始终是有限,
当请求大大超过上限时,“池”构成的系统对外界的响应并不比没有池的时候效果好多少。所以使用“池”必须考虑其面临的响应规模,

并根据响应规模调整“池”的大小。

线程池应该随着规模数调大,但是调大线程池,要在机器可承受范围之内。不能把线程池无限调大,这样相当于无限开线程一样,

多线程还是要用在规模比较小的情况

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

总结:

始综没有解决单线程遇到IO问题,单线程遇到IO,就阻塞,用的是阻塞IO模型。

阻塞IO模型就是遇到IO阻塞不处理,就在原地等着。

应该:

监测单线程IO,遇到IO了,这个线程不要阻塞。直接切换到另外一个线程运行,这样单线程效率就非常高了。

要解决的问题是:

单线程IO问题

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python计算圆周长、面积、球体体积并画出圆
Apr 08 Python
python字符串连接方式汇总
Aug 21 Python
跟老齐学Python之网站的结构
Oct 24 Python
在Python的web框架中中编写日志列表的教程
Apr 30 Python
Python轻量级ORM框架Peewee访问sqlite数据库的方法详解
Jul 20 Python
老生常谈Python startswith()函数与endswith函数
Sep 08 Python
Python 快速实现CLI 应用程序的脚手架
Dec 05 Python
python实现微信跳一跳辅助工具步骤详解
Jan 04 Python
Python设计模式之组合模式原理与用法实例分析
Jan 11 Python
Pycharm配置PyQt5环境的教程
Apr 02 Python
Python将二维列表list的数据输出(TXT,Excel)
Apr 23 Python
Python趣味实例,实现一个简单的抽奖刮刮卡
Jul 18 Python
PyTorch中常用的激活函数的方法示例
Aug 20 #Python
Pytorch抽取网络层的Feature Map(Vgg)实例
Aug 20 #Python
python批量解压zip文件的方法
Aug 20 #Python
pytorch获取vgg16-feature层输出的例子
Aug 20 #Python
python 并发编程 非阻塞IO模型原理解析
Aug 20 #Python
Python实现某论坛自动签到功能
Aug 20 #Python
python函数的作用域及关键字详解
Aug 20 #Python
You might like
10条PHP编程习惯助你找工作
2008/09/29 PHP
谈谈新手如何学习PHP 默默经典版本
2009/08/04 PHP
解析smarty 截取字符串函数 truncate的用法介绍
2013/06/20 PHP
PHP编程入门的基本语法知识点总结
2016/01/26 PHP
php使用curl获取header检测开启GZip压缩的方法
2018/08/15 PHP
jQuery AJAX 调用WebService实现代码
2010/03/24 Javascript
jQuery setTimeout传递字符串参数报错的解决方法
2014/06/09 Javascript
JS实现双击编辑可修改状态的方法
2015/08/14 Javascript
小巧强大的jquery layer弹窗弹层插件
2015/12/06 Javascript
JavaScript实现多种排序算法
2016/02/24 Javascript
javascript实现PC网页里的拖拽效果
2016/03/14 Javascript
jQuery使用$获取对象后检查该对象是否存在的实现方法
2016/09/04 Javascript
ThinkPHP+jquery实现“加载更多”功能代码
2017/03/11 Javascript
使用jQuery ajaxupload插件实现无刷新上传文件
2017/04/23 jQuery
Vue官方推荐AJAX组件axios.js使用方法详解与API
2018/10/09 Javascript
element-ui带输入建议的input框踩坑(输入建议空白以及会闪出上一次的输入建议问题)
2019/01/15 Javascript
写一个Vue loading 插件
2020/11/09 Javascript
element-ui 弹窗组件封装的步骤
2021/01/22 Javascript
[38:40]2018DOTA2亚洲邀请赛 4.6淘汰赛 mineski vs LGD 第一场
2018/04/10 DOTA
Python比较文件夹比另一同名文件夹多出的文件并复制出来的方法
2015/03/05 Python
在Python的web框架中配置app的教程
2015/04/30 Python
举例讲解Python中的list列表数据结构用法
2016/03/12 Python
Python使用PyQt5/PySide2编写一个极简的音乐播放器功能
2020/02/07 Python
selenium+python实现基本自动化测试的示例代码
2021/01/27 Python
详解HTML5中download属性的应用
2015/08/06 HTML / CSS
Clarins娇韵诗美国官网:法国天然护肤品牌
2016/09/26 全球购物
Brasty罗马尼亚:购买手表、香水、化妆品、珠宝
2020/04/21 全球购物
大专毕业生简历的自我评价
2013/10/20 职场文书
生产车间主任的个人自我鉴定
2013/10/25 职场文书
《小小竹排画中游》教学反思
2014/02/26 职场文书
银行领导班子四风对照检查材料
2014/09/27 职场文书
2015年艾滋病宣传活动总结
2015/03/27 职场文书
食品仓管员岗位职责
2015/04/01 职场文书
建党伟业电影观后感
2015/06/01 职场文书
医护人员继续教育学习心得体会
2016/01/19 职场文书
超详细教你怎么升级Mysql的版本
2021/05/19 MySQL