zoukankan      html  css  js  c++  java
  • 进程线程协程简单总结

    多道技术

    空间复用

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

    时间复用

    切换+保存状态

    切换的两种情况:

    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

  • 相关阅读:
    【报错】引入jar包import org.apache.commons.codec.digest.DigestUtils 报错,jar不存在
    【spring data jpa】使用jpa的@Query,自己写的语句,报错:org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'status' cannot be found on null
    【java】在分页查询结果中对最后的结果集List进行操作add()或remove()操作,报错:java.lang.UnsupportedOperationException
    【java】java中直接根据Date 获取明天的时间
    【java】处理时间字段 在数据库查询的时候只想要年月日,不想要时分秒 ,java中设置时间类型为年月日,java中设置Date中的时分秒为00.00.000
    【spring data jpa】 spring data jpa 中 时间格式设置between and 查询
    【mybatis】mybatis 中select 查询 select * 查询出来的数据,字段值带不出来 数据不全
    【spring mvc】spring mvc POST方式接收单个字符串参数,不加注解,接收到的值为null,加上@RequestBody,接收到{"uid":"品牌分类大”},加上@RequestParam报错 ---- GET方式接收单个参数的方法
    Centos7安装配置tomcat 9并设置自动启动
    centos7 yum安装配置redis 并设置密码
  • 原文地址:https://www.cnblogs.com/huanghongzheng/p/10999845.html
Copyright © 2011-2022 走看看