同步与异步编程


 

同步阻塞:  立即返回最终结果     
同步不阻塞: 等待 返回最终结果     
 
同步,异步,与 阻塞,非阻塞 不相关
同步 异步  ——>  强调的是结果
阻塞 非阻塞 ——> 强调的是时间,是否等待
 
 
同步与异步的区别:调用者是否得到了想要的结果
 
同步 一直执行到返回结果
异步直接返回,但不是最终结果。调用者不能通过这种调用得到结果,还要通过被调用者,使用其他方式通知调用者,来拿到最终结果
 
阻塞与非阻塞的区别在于  调用者是否在阻塞期间能做彼得事
阻塞,调用者只能 等到出结果为止
非阻塞, 调用者可以执行别的函数,不用一直等
 
同步IO,异步IO,IO多路复用
IO两个阶段:
1,数据准备阶段
2,内核空间复制回用户进程缓冲区阶段
 
发送IO的时候
内核从输入设备读写数据
进程从内核复制数据
 
同步IO
同步IO模型包括,阻塞IO,非阻塞IO,IO多路复用
 
阻塞IO
 
进程等待(阻塞),直到读写完成(全程等待)
read/write
 
非阻塞IO
进程调用read操作,如果IO设备没有准备好,立即返回ERROR,进程不阻塞,用户可以在此发起系统调用,如歌内核已经准备好,就阻塞,然后复制数据到用户空间
第一阶段,重复检查数据是否准备好,非阻塞
第二阶段,阻塞,等待服务端数据拷贝完毕为止
 
 
IO多路复用:

 

同时监控多个IO,有一个准备好了就不需要等了,开始处理,提高了同时处理IO的能力
select所有平台支持
select 作为一个监控,可以帮你看着一个进程操作是否满足条件,若满足条件,会通知用户进程
 
以select为例,将关注的IO操作 告诉select函数并调用,进程阻塞,内核“监视”select关注的文件描述符fd,
被关注的任何一个fd对应的IO准备好了数据,select返回,在使用read将数据复制到用户进程、
 
异步IO:

 

进程发起异步IO请求,立即返回一个状态,内核完成IO的两个阶段,内核给进程发送信号
 
python中IO多路复用
python的select库
实现了select库,底层的IO多路复用模块
开发平台的选择,根据不同操作系统自行选择支持的技术,这样做会提高IO处理的性能
 
selectors库
3.4版本提供足够库,高级io复用
selectors.DefaultSelector 返回当前平台最有效,性能最高的实现
没有实现windows下的IOCP,windows下退化为select
 
abstractmethod register(fileobj,events,data = None)
为selection注册一个文件对象,监视它的IO事件
 
fileobj被监控文件对象,例如socket对象
events事件,该文件对象必须等待的事件
data  本例中关联的方法,监控其状态改变后的下一步操作
将聊天软件 改写成IO多路复用的模式

 


 #将ChatServer改为IO多路复用的方式

 #从而不需要多线程的启动了
import socket
import selectors
import threading
import logging
logging.basicConfig(format="%(message)s ",level=logging.INFO)
 
class Chat_Server:
    def __init__(self,ip="127.0.0.1",port = 7888):
        self.sock = socket.socket()
        self.addr = (ip,port)
        self.event = threading.Event()
        self.selector = selectors.DefaultSelector()
 
    def start(self):
        self.sock.bind(self.addr)
        self.sock.listen()
        self.sock.setblocking(False)
        self.selector.register(self.sock,selectors.EVENT_READ,self._accept) #指向accept,说明状态后需要执行的操作,只做监控,并不执行
        threading.Thread(target=self._run).start()
 
    def _run(self):
        while not self.event.is_set():
            events = self.selector.select(1)        #将监控到的数据,传给一个容器,有容器去回调他们该做的操作
            for key,mask in events:
                callback = key.data               #key.data 指向的 是监控状态发生改变的事件该执行的函数
                callback(key.fileobj)               #用该函数,传入一个socket对象,达到其结果
 
 
    def _accept(self,sock:socket.socket):
        conn,client = sock.accept()
        conn.setblocking(False)
        key = self.selector.register(conn,selectors.EVENT_READ,self._recv)  ##recv,说明状态后需要执行的操作,只做监控,并不执行
 
    def _recv(self,conn:socket.socket):
        data = conn.recv(1024).decode().strip()
        logging.info(data)
        # conn.send(data.encode())
 
e = threading.Event()
cs = Chat_Server()
cs.start()
 
while not e.wait(1):
    cmd = input(">>>").strip()
    if cmd == "quit":
        cs.stop()
        e.wait(3)
        break

 

 

 

posted on 2017-12-24 17:48  pythonerLau  阅读(731)  评论(0编辑  收藏  举报

导航