zoukankan      html  css  js  c++  java
  • day37

    今日内容

    上周内容:

    多道技术

    空间复用

    同一时间在内存中同时加载多个程序数据,其内存之间相互隔离

    时间复用

    切换+保存状态

    切换的两种情况:

    ​ 1.一个进程遇到了IO操作时,切换到另一个进程,

    ​ 2.时间片用完后,也会被强行切换 

    多道技术的出现使计算机可以并发执行任务 

    进程:

    正在运行的程序 ,是一个资源单位, 包含程序运行的所有资源 

    为什么使用进程:

    ​ 为了并发的执行多个任务,例如TCP中客户端的并发处理 

    两种使用方式

    ​ 创建Process实例

    ​ 继承Process类

    注意:开启进程的代码必须放在 判断下面 , 因为windows平台开启子进程时,会导入代码执行一遍 来回去要执行的任务 

    守护进程:

    ​ 被守护进程结束时守护进程也会随之结束 

    常用属性和方法

    ​ join  提高子进程的优先级 使得子进程先于父进程执行  父进程需要等待子进程完成后才能继续执行 

    ​ daemon 设置为守护进程

    ​ is_alive 是否存活 

    ​ pid   进程id

    ​ terminate  终止进程 

    ​ exitcode 获取进程的退出码

    ​ name 名字 

    僵尸和孤儿

    孤儿  父进程先于子进程结束了,子进程会被操作系统接管 

    僵尸  在linux有一个机制,可以保证父进程在任何时候都可以访问到子进程的一些信息,所以子进程结束后并不会立即清除所有数据 ,这时候就是僵尸进程 

    僵尸进程会占用一些系统资源,需要父进程调用waitpid来进行清理, 

    python会自动清理僵尸进程 

    IPC

    ​ 进程间通讯 

    ​ 因为每个进程之间内存是物理隔离,很多时候我们需要将数据讲给另外一个进程 ,例如:美团要把订单信息交给支付宝

    ​ 1.共享文件

    ​ 特点:数据量没什么限制,但是读写速度慢 

    ​ 2.共享内存区域

    ​ 特点:数据量不能太大,速度快 

    ​ 3.管道

    ​ 单向通讯,传输的是二进制 

    ​ 4.socket 

    ​ 编程较复杂

    主要方式:共享内存

    ​ 1.Manager 提供一系列常用的数据结构,但是没有处理锁的问题 

    ​ 2.进程Queue  是一种特殊的容器,先进先出,并且进程队列支持IPC    已经处理好锁了

    互斥锁

    ​ 相互排斥的锁,mutex 

    ​ 锁是什么: 本质就是一个标志,可以限制代码是否能够执行 

    ​ 为什么需要锁:多个进程要操作同一个资源时,可能造成数据错乱 

    ​ 加锁会导致并发变成串行,降低了效率,保证了数据安全 

    与join的区别

    ​ join会使得整个进程代码全部串行,并且主进程也无法继续执行 

    ​ 锁可以控制部分代码串行,其余任然并发,效率比join高  

    ​ 锁的粒度越小效率越高

    消费者生产者模型

    ​ 要解决的问题,生产者用户消费者处理能力不平衡,  如果串行执行任务 效率低下

    ​ 解决的方案:

    ​ 1.将生产者与消费者节考耦合

    ​ 2.将双方并发执行 

    3.提供一个共享的容器 

    ​ 4.生产者将数据放入容器

    ​ 5.消费者从容器获取数据来处理 

    ​    

    是否可以使用多线程来完成生产者消费者模型  必须可以

    在线程中需不需要使用队列呢??         建议使用 

    抢票案例:

    ​ 数据出了问题,一张票 卖给了多个人  ,原因就是因为并发了 

    ​ 加锁解决:  将并发修改的代码加锁变成串行

    多线程

    线程是: CPU最小的执行单位 ,(操作系统最小调度运算单位),是一个固定执行过程的总称

    一个进程至少包含一个线程,称之为主线程 ,是由操作系统自动开启的 

    ​ 运行过程中自己开启的线程 称之为子线程

    ​ 线程间没有父子关系   ,  例如a-b-c   b和c都是a的子线程 

    线程对比进程:

    ​ 开启速度快,开销小 

    ​ 同一个进程中所有线程数据共享

    守护线程:

    ​ 守护线程会在所有非守护线程结束时随之结束,当然守护线程可能提前结束了 

    使用方式:

    ​ 与进程一样,开线程的代码可以放任何位置

    常用方法:

    ​ currentthread()  获取当前的线程对象

    ​ enumerate()   获取所有运行中的线程对象

    ​ active_count   获取存活的线程数量

    线程队列

    ​ queue 

    ​ Queue  普通队列

    ​ LifoQueue  先进后出队列 模拟堆栈

    ​ PriorityQueue  优先级队列    可以比较大小的数据都能存到其中   取出时按照从小到大取出

    ​ 运算符重载  可以使自定义对象支持 算术运算符  

    线程锁

    ​ Lock 互斥锁

    ​ Rlock 递归锁    同一个线程可以多次锁定或解锁 ,锁了几次就解几次 

    ​ semaphore  信号量   可以限制同一时间多少线程可以并发执行

    ​ 死锁问题  当一个资源的访问,需要具备多把锁时,然而不同的锁被不同线程持有了,陷入相互等待中 

    ​ 1.,尽量使用一个锁 , 设置超时 释放手里的锁, 

    ​ 2.抢锁时 按顺序抢 

    GIL锁

    ​ GIL全程 全局解释器锁 ,是一把互斥锁,是非常重要的,为了防止多个本地线程同一时间执行python的字节码,

    ​ 因为Cpython的内存管理不是线程安全的(非线程安全的),越来越多的特性依赖于这把锁, 如果去掉这个锁的话, 会有很代码需要重构, 并且需要程序自己来处理很多的安全问题,这是非常复杂的 

    造成的问题

    ​ cpython多个线程不能并行,丧失了多核优势 

    带来的好处

    ​ 保证了线程安全,

    如何避免带来的性能影响

    ​ 首先判断任务的类型 ,分IO密集型   计算密集型  ​ 是IO密集型任务,使用多线程即可,由于大部分时间消耗在IO等待上了,所以影响不大

    ​ 计算密集型,只能开启多进程 

    与自定义锁的区别

    ​ GIL只能 保证解释器级别数据安全,如果我们自己开启了一些不属于解释器的资源例如文件. 必须自己加锁来处理 

    加锁和释放

    ​ 拿到解释器要执行代码时立即加锁

    ​ 遇到IO时解锁    

    ​ CPU时间片用完了   注意解释器的超时时间 与CPU的超时时间不同   为100nm 

    进程池  线程池 

    ​ 池即容器

    ​ 线程池 即存储线程的容器 

    ​ 为什么使用线程池

    ​ 1.可以限制线程 数量      通过压力测试 来得出最大数量 

    ​ 2.可以管理线程的创建以及销毁 

    ​ 3.负责任务的分配 

    ​ 使用

    ​ 创建池

    ​ submit提交任务   异步任务    将返回future对象    调用add_done_callback 可以添加回调函数 

    ​ 在任务结束时还会自动调用 回调函数并传入 future本身, 调用result()可以拿到任务的结果 

    ​ 不常用的两种方式

    ​ shutdown  可以关闭线程池,会阻塞直到所有任务全部完成 

    ​ 直接调用result  如果任务没有完成会进入阻塞状态  

    异步同步

    ​ 同步: 任务提交后必须原地等待任务执行结,才能继续执行 

    ​ 异步: 提交任务后可以立即执行后续代码  

    ​ 异步效率高

    ​ 如何实现异步:

    ​ 多线程,多进程

    ​ 同步异步指的是   任务的执行方式 

    异步回调

    ​ 异步回调  本质就是一个普通函数,该函数会在任务执行完成后自动被调用 

    ​ 线程池, 谁有空谁处理

    ​ 进程池,都是在父进程中回调 

    协程

    ​ 协程本质是在单线程下实现并发

    ​ 协程是一种轻量级线程,也称为微线程,可以由应用程序自己来控制调度

    ​ 好处:

    ​ 可以再一个任务遇到IO操作时,自主切换到自己进程中其他线程 

    ​ 如果任务足够多,就可以充分利用CPU的时间片 

    ​ 缺点:

    ​ 仅适用于IO密集型任务 ,计算密集型,如果是单线程话的串行效率更高 ,建议使用多进程来处理 

    ​ 当单个任务耗时较长时  协程效率反而不高

     

    我们目的就是尽可能的提高效率 

    ​ 进程 线程  协程 

    ​ 可以使 多进程 + 线程 + 协程      UWSGI

    协程对比多线程:

    ​ 线程池可以解决一定的并发数量,但是如果并发量超过了机器能承受最大限制,线程池就出现瓶颈了

    协程的使用

    ​ gevent   需要自己安装 

    ​ 1.先打补丁     (本质是将原本阻塞的代码替换成非阻塞的代码)

    ​ 2.gevent.spawn(任务)  来提交任务 

    ​ 3.必须保证主线不会结束 使用join  或是join  all

    IO模型

    ​ 模型就是解决某个问题的套路 

    ​ IO问题:

    ​ 输入输出 

    ​ 我要一个用户名用来执行登陆操作,问题用户名需要用户输入,输入需要耗时,  如果输入没有完成,后续逻辑无法继续,所以默认的处理方式就是 等

    ​ 将当前进程阻塞住,切换至其他进程执行,等到按下回车键,拿到了一个用户名,再唤醒刚才的进程,将状态调整为就绪态

    以上处理方案  就称之为阻塞IO模型

    存在的问题:

    ​ 当执行到recv时,如果对象并没有发送数据,程序阻塞了,无法执行其他任务

    解决方案:

    ​ 多线程或多进程,

    ​ 当客户端并发量非常大的时候,服务器可能就无法开启新的线程或进程,如果不对数量加以限制 服务器就崩溃了

    ​ 线程池或进程池

    ​ 首先限制了数量 保证服务器正常运行,但是问题是,如果客户端都处于阻塞状态,这些线程也阻塞了

    ​ 协程:

    ​ 使用一个线程处理所有客户端,当一个客户端处于阻塞状态时可以切换至其他客户端任务  

     

    非阻塞IO模型

    ​ 阻塞IO模型在执行recv 和 accept  时 都需要经历wait_data 

    ​ 非阻塞IO即 在执行recv 和accept时 不会阻塞 可以继续往下执行

    ​ 如何使用:

    ​ 将server的blocking设置为False 即设置非阻塞 

    ​ 存在的问题 :

    ​ 这样一来 你的进程 效率 非常高 没有任何的阻塞

    ​ 很多情况下 并没有数据需要处理,但是我们的进程也需要不停的询问操作系统  会导致CPU占用过高

    ​ 而且是无意义的占用 

  • 相关阅读:
    PowerDesigner建立与数据库的连接,以便生成数据库和从数据库生成到PD中。[Oracle 10G版]
    如何进行数据库,比如ORACLE,SQL SERVER的逆向工程,将数据库导入到PowerDesigner中
    PowerDesigner PDM 生成SQL脚本 去除双引号方法
    PowerDesigner删除外键关系,而不删除外键列[转] 及编码格式
    powerdesigner导出sql
    SQLSERVER存储过程基本语法
    jQuery选择器大全(48个代码片段+21幅图演示)
    fiddler使用
    基于.NET平台常用的框架技术整理
    Windows 按键
  • 原文地址:https://www.cnblogs.com/Fzhiyuan/p/11000770.html
Copyright © 2011-2022 走看看