python开发之异步编程

python网络编程目录

  • 异步编程
    • 1.进程间通信
      • 进程
        • 进程间通信的几种类型
      • 线程(lightweight process)
      • 线程VS进程
      • IO模型
      • 并发VS并行
      • 异步vs同步
    • 2.多线程与多进程的用法
      • 计算密集型vs I/O密集型
      • GIL
      • 多线程
      • 多进程
    • 3.协程的好处与用法
      • 协程
      • yield
      • yield from
    • 4.开始使用Async,Await
    • 5.Http框架Aiohttp
    • 6.案例异步爬虫

异步编程

1.进程间通信

进程间通信(IPC,Inter-Process Communication)是指在不同进程之间传播或交换信息

IPC的方式通常有管道(包括 无名管道和命名管道)、消息队列、信号量、共享存储、Socket、Streams等、

进程

进程是具有一定功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。

每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信
python开发之异步编程_第1张图片

进程间通信的几种类型

管道,通常是指无名管道,是Unix系统IPC最古老的形式

  1. 半双工(即数据只能在一个方向上流动),具有固定的读端和写端。
  2. 只能用于具有亲缘关系的进程之间的通信(父子进程或者兄弟进程之间)。
  3. 可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write等函数,但它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中
  4. 通过系统函数int pipe(int __pipedes[2])进行创建
    FIFO,命名管道,一种特殊文件类型
  5. FIFO可以在无关的进程之间交换数据,与无名管道不同
  6. FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中,命名管道,FIFO是一种特殊文件类型
    命名管道有mkfifo函数创建,打开用open。
    FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在于它们创建与打开的方式不同,这些工作完成之后,它们具有相同的语义。
    消息队列
    消息队列是消息的链接表,存放于内核中。一个消息队列又一个标识符(即队列ID)来标识
  7. 消息队列是面向记录的,其中消息具有特定的格式以及特定的优先级
  8. 消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除
  9. 消息队列可以实现消息的随机查询,消息不一定要一先进先出的次序读取,也可以按照类型读取
    信号量

信号量(semaphore)与已经介绍过的IPC结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据

  • 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
  • 信号量基于操作系统PV操作,程序对信号量的操作都是原子操作。
  • 每次对信号量的PV操作不仅限于对信号量的加1或减1,而且可以加减任意正整数。
  • 支持信号量组
    共享内存
    共享内存(Shared Memory)指的是两个或多个进程共享一个给定的存储区
  • 共享内存是最快的一种IPC,因为进程是直接堆内存进行存取的。
  • 因为多个进程可以同时操作,所以需要进行同步。
  • 信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。
    PV操作
    这个是狄克思特拉用荷兰文定义的,因为在荷兰文中 ,通过叫passeren,释放叫做VRIJGEVEN,PV 操作因为得名
    原子操作
    如果这个操作所处的层(layer)的更高层不能发现其内部实现与结构,那么这个操作就是一个原子(atomic)操作
    原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序不可以被打乱,也不可以被切割而只执行其中一部分。
    进程的基本特征
    动态性
    并发性
    独立性
    异步型
    进程的状态转换
    python开发之异步编程_第2张图片
    进程控制块(Processing Control Block)
    也称为进程描述块(Process Descriptor)操作系统核心中 的一种数据结构,主要标识进程状态。在创建进程时首先建立PCB,它伴随进程运行的整个过程,知道进程撤销而报销。系统可以利用 PCB来控制和管理进程,所以说PCB(进程控制块)是系统感知进程存在的唯一标志。
  • 程标识符(Process ID)、进程名、用户标识符(user ID)进程组关系。每个进程都必须有一个标识符,通常是一个整数。
  • 前状态、优先级、程序的磁盘地址、代码开始地址、进程队列指针、通信信息
  • 拟地址空间的状况、打开文件列表
  • 存器值(通用寄存器。程序计数器PC、程序状态字PSW、栈指针)、指向该进程页表的指针
    unix系统 中的几个进程 控制操作
    fork():通过复制调用进程来建立新的进程,是最基本的进程建立过程(创建进程,昂贵,消耗资源)
    exec():包括一系列系统调用 ,他们是通过用一段新的程序代买覆盖原来的地址空间,实现进程执行代码的转换。
    wait():提供初级进程同步操作,能使一个进程等待另外一个进程结束。
    exit():用来终止一个进程的执行
    python开发之异步编程_第3张图片
    IPC:父进程向子进程传递数据容易,子传递给父进程很难

线程(lightweight process)

python开发之异步编程_第4张图片

python开发之异步编程_第5张图片
python开发之异步编程_第6张图片
线程:进程的一个可调度的实体CPU调度的基本单位 ,不拥有系统资源消耗资源少,多线程可以相互交互
线程之间共享:

  • 进程指令
  • 大多数数据
  • 打开的文件(描述符)
  • 信号处理函数和信号处理
  • 用户ID和组ID
    线程的独立信息:
  • 线程ID
  • 寄存器集合,(程序计数器和栈指针)
  • 栈(用于存放局部变量和返回地址)
  • erron
  • 信号掩码
  • 优先级
    现成的额创建:
    系统底层的pthread_create创建线程
    在POXIS规范的系统中称pthread

线程VS进程

  • 地址空间
    线程是进程的执行单元

  • 资源使用
    进程是资源分配的单位

  • CPU调度
    线程是CPU调度的基本单位

  • 并发

  • 是否独立
    线程不能独立运行

IO模型

I/O操作的两个阶段
1.内核等待数据
2.从内核向进程复制数据
python开发之异步编程_第7张图片

  • 阻塞式
    python开发之异步编程_第8张图片
  • 非阻塞式
    python开发之异步编程_第9张图片
  • I/O复用
    当客户处理多个描述符(一般是交互式输入或网络套接字)必须适用I/O复用当一个客户处理多个套接字时,这种情况很少见,但也能出现
    当一个TCP服务器既要处理监听套接字,又要处理已连接套接字,一般就要适用I/O复用
    如果一个服务器既要适用TCP又要适用UDP一般就使用I/O复用
    如果一个服务器要处理多个服务或者多个协议,一般就要使用I/O复用
    python开发之异步编程_第10张图片
  • 信号驱动式
    python开发之异步编程_第11张图片
  • 异步I/O
    python开发之异步编程_第12张图片

python开发之异步编程_第13张图片

并发VS并行

python开发之异步编程_第14张图片
python开发之异步编程_第15张图片

异步vs同步

python开发之异步编程_第16张图片
python开发之异步编程_第17张图片

2.多线程与多进程的用法

计算密集型vs I/O密集型

python开发之异步编程_第18张图片
python开发之异步编程_第19张图片

GIL

Global Interpreter Lock
python开发之异步编程_第20张图片
python开发之异步编程_第21张图片
python开发之异步编程_第22张图片
python开发之异步编程_第23张图片
什么时候使用多线程?
I/O密集型:文件读写,网络传输
什么时候使用多进程?
CPU密集型的计算问题

多线程

多线程的注意问题:
锁 的
python开发之异步编程_第24张图片
linux底层:
互斥锁mutex:mutual exclusion
保护共享变量:解决多个线程更改一个共享变量的问题,提供互斥机制。
互斥锁是类型 为pthread_mutes_t的变量

python开发之异步编程_第25张图片
线程启动程序

#!/usr/bin/env python3
# -*-coding :utf-8 -*-
__author__ = 'gyz'
from threading import Thread
import time
def countdown(n):
    while n > 0 :
        print('倒数开始 :',n)
        n -= 1
        time.sleep(1)


def main():
    # countdown()
    t = Thread(target=countdown,args=(5,))
    t.start()

if __name__ == '__main__':
    main()

多进程

3.协程的好处与用法

协程

yield

yield from

4.开始使用Async,Await

5.Http框架Aiohttp

6.案例异步爬虫

你可能感兴趣的:(python多线程,python开发)