zoukankan      html  css  js  c++  java
  • 15 并发编程-(IO模型)

    一、IO模型介绍

    1、阻塞与非阻塞指的是程序的两种运行状态

    阻塞:遇到IO就发生阻塞,程序一旦遇到阻塞操作就会停在原地,并且立刻释放CPU资源

    非阻塞(就绪态或运行态):没有遇到IO操作,或者通过某种手段让程序即便是遇到IO操作也不会停在原地,执行其他操作,力求尽可能多的占有CPU

    2、同步与异步指的是提交任务的两种方式:

    同步调用:提交完任务后,就在原地等待,直到任务运行完毕后,拿到任务的返回值,才继续执行下一行代码

    异步调用:当进程执行到一个IO(等待外部数据)的时候,不需要等待,待数据接收成功后,再回来处理。

    1.io模型
    提交任务得方式:
        同步:提交完任务,等结果,执行下一个任务
        异步:提交完,接着执行,异步 + 回调  异步不等结果,提交完任务,任务执行完后,会自动触发回调函数
    同步不等于阻塞:
        阻塞:遇到io,自己不处理,os会抢走cpu ,解决办法:监测到io,gevent切换到其他任务,类似欺骗os
        非阻塞:cpu 运行
    IO分类:
        1.阻塞IO        blocking IO
        2.非阻塞IO      nonblocking IO
        3.IO多路复用    IO multiplexing
        4.信号驱动IO    signal driven IO     用得比较少 
        5.异步IO        asynchronous IO
    遇到IO: 卡
        网络IO: 原地阻塞
        1.server端什么样得操作属于IO行为     
            # accept recv send 阻塞操作   accept recv 明显得等  send 不会明显等,但是一种io行为  
        2.为什么IO行为会让有在原地等待的效果  
    
    
    3.非阻塞io:
    自己监测io 遇到io 就切 并且把 单线程得效率提到最高
    导致得问题:
        1.当有数据来得时候,cpu 在做其他得事情,不会立即响应
        2.服务端没有任何阻塞,说白了,就是死循环,cpu会一直运转,线程处于就绪状态,大量占用cpu ,做无用,这个线程会一直问cpu,有数据没,有数据没
    不推荐使用
    
    
    4.多路复用io:
        wait copy  还多了select  中间有个中介存在,帮问os 有没有数据
        但是如果中介 只有1个 效率不如 阻塞效率
        但是如果中介监测多个套接字 ,性能高就是:同时监测多个套接字问os系统好了没  就比阻塞io效率高
         监测套接字得io行为
        服务端得套接字有几类:server conn
    
        select 阻塞io 效率高
           比非阻塞io 效率也高 ,一直做无用
    
    总结:
       同时监测多个套接字
       列表 循环 慢 假设列表数据多,循环 效率低  监测套接字好没好 从头到尾 循环1遍
       select  列表循环  效率低
       poll   可接收得列表数据多 效率也不高
       epoll 效率最高得 异步操作 每个套接字身上绑定个回调函数,谁好了谁触发回调,(就不用去遍历了 效率低)
       epoll  windows 不支持
              linux 支持
       selectors 模块  自动根据操作系统选择
       poll
       epoll

    二、阻塞IO模型

    默认情况下,所有的socket都是blocking模型,

    实际上,除非特别指定,几乎所有的IO接口 ( 包括socket接口 ) 都是阻塞型的。

    这给网络编程带来了一个很大的问题,如在调用recv(1024)的同时,线程将被阻塞,在此期间,线程将无法执行任何运算或响应任何的网络请求。

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

    三、非阻塞IO模型

     

    在非阻塞式IO中,用户进程其实是需要不断的主动询问kernel数据准备好了没有。

    from socket import *
    
    server = socket(AF_INET, SOCK_STREAM)
    server.bind(('127.0.0.1',8083))
    server.listen(5)
    server.setblocking(False)
    print('starting...')
    
    rlist=[]
    wlist=[]
    while True:
    
        try:
            conn, addr = server.accept()
            rlist.append(conn)
            print(rlist)
        except BlockingIOError:
            # print('干其他的活')
    
            #收消息
            del_rlist = []
            for conn in rlist:
                try:
                    data=conn.recv(1024)
                    if not data:
                        del_rlist.append(conn)
                        continue
                    wlist.append((conn,data.upper()))
                except BlockingIOError:
                    continue
                except Exception:
                    conn.close()
                    del_rlist.append(conn)
    
            #发消息
            del_wlist=[]
            for item in wlist:
                try:
                    conn=item[0]
                    data=item[1]
                    conn.send(data)
                    del_wlist.append(item)
                except BlockingIOError:
                    pass
    
            for item in del_wlist:
                wlist.remove(item)
    
            for conn in del_rlist:
                rlist.remove(conn)
    
    server.close()
    View Code

    四、多路复用IO模型

    五、异步IO模型

    六、各种IO模型对比

    七、了解selectors模块的使用

  • 相关阅读:
    How to change hostname on SLE
    How to install starDIct on suse OS?
    python logging usage
    How to reset password for unknow root
    How to use wget ?
    How to only capute sub-matched character by grep
    How to inspect who is caller of func and who is the class of instance
    How to use groovy script on jenkins
    Vim ide for shell development
    linux高性能服务器编程 (二) --IP协议详解
  • 原文地址:https://www.cnblogs.com/foremostxl/p/9738068.html
Copyright © 2011-2022 走看看