• day_30


    昨日回顾

    进程互斥锁

    让并发变成串行,牺牲了效率,保证数据安全.
    mutex = Lock()
    加锁
    mutex.acquire()
    释放锁
    mutex.release()

    队列

    相当于在内存中开启了一个空间,可以存放一堆数据,这堆数据都得遵循"先进先出".
    管道(阻塞) + 锁

    q = Queue()
    
    添加数据
    
    q.put(1)
    
    若队列满了,会原地等待
    
    q.put(2)
    
    若队列满了,不会等待直接报错
    
    q.put_nowait(2)
    获取数据,遵循先进先出
    若队列中没数据,会原地等待
    q.get()  # 1
    若队列中没数据,会直接报错
    q.get_nowait()  # 1
    q.empty()  # 判断队列是否为空
    q.full()  # 判断队列是否满了
    

    IPC进程间通信

    通过队列让进程间实现通信

    生产者与消费者

    生产者:生产数据的

    消费者:使用数据的

    目的是为了解决供需不平衡的问题

    线程

    1.什么是线程?
    进程: 资源单位
    线程: 执行单位
    注意: 只要开启一个进程就会有一个线程(主线程).
    主线程会在进程结束时,一并销毁.

    2.为什么要使用线程?
    节省内存资源

    开启进程:

    1. 开辟一个新的内存空间
    2. 会自带一个主线程
      开启线程:
    3. 一个进程内可以开启多个线程
    4. 开启线程的资源远小于进程

    GIL全局解释锁

    python解释器

    1. Cpython(C语言编写)
    2. Jpython(Java编写)
    3. Ppython(Python编写)

    GIL全局解释锁

    基于CPython来研究全局解释器锁,因为CPython的内存线程不是安全的

    1. GIL本质上是一个互斥锁
    2. GIL是为了阻止同一个进程内多个线程同时执行(并行)
    3. GIL的存在就是为了保证线程安全

    注意:多个线程过来执行,一旦遇到IO操作,就会立马释放GIL解释器锁,交给下一个先进来的线程

    多线程的作用

    计算密集型程序

    • 在单核情况下,若一个任务需要10s
      • 开启进程,消耗资源大,执行4个进程需要40s
      • 开启线程,消耗资源小,执行4个线程需要40s
    • 在多核情况下,若一个任务需要10s
      • 开启进程,并行执行,效率较高,执行4个进程需要10s
      • 开启线程,并发执行,效率较低,执行4个线程需要40s

    IO密集型程序

    • 在单核情况下,若一个任务需要10s
      • 开启进程,消耗资源大,执行4个进程需要40s
      • 开启线程,消耗资源小,执行4个线程需要40s
    • 在多核情况下,若一个任务需要10s
      • 开启进程,并行执行,效率小于线程,因为遇到IO会立即切换CPU执行权限,执行4个进程需要10s = 开启进程的额外时间
      • 开启线程,并发执行,效率高于进程,执行4个线程需要40s

    死锁现象

    死锁是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程 ,解决方式就是递归锁

    递归锁

    递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。

    这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。

    信号量

    信号量Semaphore管理一个内置的计数器,
    每当调用acquire()时内置计数器-1;
    调用release() 时内置计数器+1;
    计数器不能小于0;当计数器为0时,acquire()将阻塞线程直到其他线程调用release()

    注意: 与进程池是完全不同的概念,进程池Pool(4),最大只能产生4个进程,而且从头到尾都只是这四个进程,不会产生新的,而信号量是产生一堆线程/进程

    线程队列

    线程队列

    queue队列:使用import queue,用法与进程Queue一样

    先进先出

    FIFO队列: 先进先出 class queue.Queue(maxsize=0)

    后进先出

    LIFO队列: 后进先出 class queue.LifoQueue(maxsize=0 )

    优先级队列

    优先级队列: 根据参数内,数字的大小进行分级,数字值越小,优先级越高class queue.PriorityQueue(maxsize=0)

    put进入一个元组,元组的第一个元素是优先级(通常是数字,也可以是非数字之间的比较),数字越小优先级越高

  • 相关阅读:
    Redis 简介
    图片懒加载、selenium和PhantomJS
    Python网络爬虫之三种数据解析方式
    Scrapy框架之CrawlSpider
    Scrapy 框架
    python 网络爬虫概念与HTTP(s)协议
    Mysql概念及基本操作
    Python re 模块
    线程与进程应用场景
    全局解释器锁 GIL
  • 原文地址:https://www.cnblogs.com/maqiaobin/p/11728778.html
Copyright © 2020-2023  润新知