IO模型

 1 import time
 2 import random
 3 from threading import local,Thread
 4 
 5 loc = local()
 6 def func2():
 7     global loc
 8     print(loc.name, loc.age)
 9 
10 def func(name,age):
11     global loc
12     loc.name = name
13     loc.age = age
14     time.sleep(random.random())
15     func2()
16 
17 Thread(target=func, args=('wang', 22)).start()
18 Thread(target=func, args=('zhao', 11)).start()
19 #zhao 11      
20 #wang 22
21 #多个线程之间,使用threading.local对象,可以实现多个线程之间的数据隔离
local的概念

IO

同步:一件事做完再做另一件事

异步:同时做很多事(相对论  多进程  多线程   协程   异步的程序)

阻塞:sleep  input  join  shutdown  get  acquire  wait           accept  recv  recvfrom

非阻塞:setblocking(False)

网络IO模型  socket

  用socket就会用到accept,recv,recvfrom等方法,正常情况下,它们都是阻塞的,如果setblocking(False) 整个程序就会变成一个非阻塞的程序了

阻塞IO

阻塞IO的recv做了哪些事

 

wait for date 阶段   阻塞    copy date 阶段  阻塞

非阻塞IO

 1 #server
 2 import socket
 3 sk = socket.socket()
 4 sk.bind(('127.0.0.1', 8520))
 5 sk.setblocking(False)
 6 sk.listen()
 7 conn_lst = []  #建一个存储conn的列表
 8 del_lst = []   #建一个挂断的列表,conn关闭加入到此列表然后删除
 9 while True:
10     try:
11         conn, addr = sk.accept()
12         conn_lst.append(conn) #每次接收到的新的conn都加入到列表中
13     except BlockingIOError:
14         for conn in conn_lst:
15             try:
16                 conn.send(b'hello')
17                 print(conn.recv(1024))
18             except (NameError,BlockingIOError):pass #异常处理
19             except ConnectionAbortedError:  #客户端挂断会产生此异常
20                 conn.close()
21                 del_lst.append(conn)
22         for del_conn in del_lst:
23             conn_lst.remove(del_conn)
24         del_lst.clear()
25 
26 #client
27 import socket
28 sk = socket.socket()
29 sk.connect(('127.0.0.1', 8520))
30 
31 print(sk.recv(1024))
32 sk.send(b'byebye')
33 sk.close()
非阻塞IO

没有并发编程的机制   同步的程序

非阻塞的特点:程序不会在某一个连接的recv或者sk的accept上进行阻塞,就会有更多的时间来做信息的收发工作

太多的While True  高速运行着   大量的占用了cpu导致了资源的浪费

阻塞IO的问题:一旦阻塞就不能继续运行了

非阻塞IO的问题:给cpu造成了很大的负担

IO多路复用

 1 import select
 2 import socket
 3 #用来操作操作系统中的select(IO多路复用)机制
 4 sk = socket.socket()
 5 sk.bind(('127.0.0.1', 8520))
 6 sk.setblocking(False)   #非阻塞
 7 sk.listen()
 8 
 9 r_lst = [sk, ]   # 用来存储sk,conn1,conn2...
10 while True:
11     r_l, _, _ = select.select(r_lst, [], [])
12     for item in r_l:
13         if item is sk:
14             conn, addr = sk.accept()
15             r_lst.append(conn)
16         else:
17             try:
18                 print(item.recv(1024))
19                 item.send(b'hello')
20             except ConnectionAbortedError:
21                 item.close()
22                 r_lst.remove(item)
IO多路复用

IO多路复用机制

select  windows、mac、linux

  底层是操作系统的轮询,有监听对象个数的限制,随着个数的增加效率降低

poll   mac、linux

  其他的与select的一致,在select的基础上增加了监听对象的个数的限制,无限个数

epoll   mac、linux

  给每一个要监听的对象都绑定了一个回调函数,不再受到随着个数增加而降低效率的影响

socketserver:IO多路复用+threading线程

selectors模块:帮助你在不同的操作系统上进行IO多路复用机制的自动筛选

--------------------------->

简述 进程、线程、协程的区别 以及应用场景?
进程
场景 利用多核、高计算型的程序、启动数量有限
进程是计算机中最小的资源分配单位
进程和线程是包含关系 每个进程中都至少有一条线程
可以利用多核,数据隔离
创建 销毁 切换 时间开销都比较大
随着开启的数量增加 给操作系统带来负担

线程 高IO型 调度是我们不能干预的 我们只能写我们自己的逻辑
场景 一些协程协程现有的模块不能完成帮助我们规避IO操作的功能 适合使用多线程 urllib
被CPU调度的最小单位,线程的切换时操作系统完成的
在cpython解释器下不能利用多核,数据共享
创建 销毁 切换 时间开销都比进程小很多
随着开启的数量增加 给操作系统带来负担

协程 高IO型 用户可以自己控制的 我们能否抢占更多的资源完全取决于我们切换策略
场景 一些通用的场景 可以用协程现有的模块来规避一些IO操作适合使用协程
协程的切换工作是用户完成的
是一个线程,完全不能利用多核,不会产生数据不安全的现象
多个任务之间互相切换不依赖操作系统,无论开启多少个协程都不会给操作系统带来负担

#######################
# IO模型
# 阻塞IO : 原生socket 默认阻塞IO
# 非阻塞IO :原生socket setblocking(False)
# 永远在就绪和运行之间切换
# 能够最大限制的利用CPU、但是不排除过度利用的现象
# IO多路复用 -- 其次
# 利用一个操作系统提供给你的代理机制
# 帮助你来监听网络IO对象的读写事件
# 异步IO -- 最好
# 等待数据阶段和拷贝数据阶段都不需要用户处理
# 所有的操作都由操作系统替你完成
# 拷贝数据阶段 只有异步IO是不需要阻塞的

# 研究开源的工具
# 把源码给你看
# 对新工具的探索精神
posted @ 2018-09-27 17:41  .why  阅读(212)  评论(0)    收藏  举报
Live2D