进程间通信之共享内存
通信原理:在内存空间开辟一个区域,对多个进程可见,进程可以写入内容
或读取内容,但是每次写入的内容会覆盖之前的内容
from multiprocessing import Value,Array
obj = Value(ctype,obj) (只能存单个数据)
功能:开辟共享内存空间
参数:ctype 字符串,表示共享内存中要存储的数据类型
常用类型:int--->'i'
float--->'f'
char(bytes)---->'c'
obj 共享内存中放入的初始化数据
obj.value 对该属性的修改和使用即对共享内存数据的修改使用
obj = Array(ctype,obj)
功能:创建共享内存
参数:ctype 要存储的而数据类型
obj 存入一个结构化的数据(列表,bytes字符串)表示共享内存中的初始数据
传入正整数 则表示在共享内存中开辟指定大小的数据空间
返回值: 共享内存对象
* 可以通过遍历可以获取每个值,支持索引操作
例如: obj[2] 表示获取共享内存中第三项,对其修改即对共享内存修改
* 如果存入的是字符串,可以通过obj.value直接打印整个字符串
管道 消息队列 共享内存
开辟空间 内存 内存 内存
读写方式 两端读写 先进先出 覆盖之前的内容
效率 一般 一般 较高
特点 多用于父子进程 有很多第三方队列 需要注意同步操作
信号量(信号灯)
原理:给定一个数量,多个进程均可见,多个进程可以通过方法操作数量,达到协同工作的目的
from multiprocessing import Semaphore
sem = Semaphore(num)
功能:创建信号量对象
参数:信号量的初始值
返回值:信号量对象
sem.acquire() 将信号量减1 当信号量为0时会阻塞
sem.release() 将信号量加1
sem.get_value() 获取信号量数量
多任务编程之线程(Thread)
什么是线程?
1.线程也是多任务编程方法
2.也可以使用计算机的多核资源
3.线程被成为轻量级的进程
4.线程是系统分配内核的最小工作单元
线程特征
1.一个进程可以包含多个线程
2.线程是一个运行的过程,需要消耗计算机资源
3.多个线程的执行相互不影响不干扰
4.线程的创建销毁,消耗的资源远远小于进程
5.一个进程中的多个线程,共享这个进程的系统资源
6.每个线程也有自己特有的特征,比如ID,指令集等
threading 模块创建线程
from threading import Thread
t = Thread()
功能: 创建线程对象
参数:target 绑定线程函数
args 元组 给线程函数位置传参
kwgars 字典 给线程函数键值对传参
name 线程名称 默认为Thread-1
t.start() 启动线程,自动运行线程函数
t.join([timeout]) 回收线程
线程对象属性
t.name 线程名称
t.setName() 设置名称
t.getName() 获取名称
t.is_alive() 线程状态
threading.currentThread() 在线程函数中获取当前线程对象
t.daemon 默认为False此时主线程退出,分支线程会继续执行
如果设置为True则主线程退出,分支线程也随之退出
t.setDaemon(True) 设置daemon属性
t.isDaemon() 判断daemon的值
* 在start前设置,通常不和join同用
创建自己的线程类
步骤:
1.继承Thread
2.添加自己属性写__init__,加载父类init
3.重写run方法
4.使用自己的类生产线程对象,调用start启动线程,此时会自动运行run方法作为线程执行
线程间通信
通信方法:
使用进程空间中全局变量通信
注意事项:共享资源的争夺,往往需要同步互斥机制协调
线程的同步互斥
共享资源(临界资源):多个线程都可以操作的资源称为共享资源
临界区:指一段代码段,对临界资源操作的代码段称为临界区
同步:同步是指一种合作关系,为完成任务,多进程或者线程之间形成一种协调,按照必要的步骤
有序执行操作临界资源
互斥:互斥是一种制约关系,当一个进程或者线程使用临界资源时会进行加锁处理,此时另一个进程
或者线程就无法操作临界资源,直到解锁后才能操作
线程的同步互斥方法:
线程 Event
from threading import Event
e = Event() #创建线程Event对象
e.wait([timeout])
功能:阻塞函数,等待e被设置
参数:超时时间
e.set() 将e变为设置状态
e.clear() 将e变回未设置状态
e.is_set() 判断当前e的状态,被设置得到True否则False
线程锁 Lock
from threading import Lock
lock = Lock() 创建锁对象
lock.acquire() 上锁 如果已经上锁调用此函数会阻塞
lock.release() 解锁
with lock 上锁操作
....
....
with 语句块结束自动解锁
python线程的GIL问题 (全局解释器锁)
GIL:由于python解释器设计中加入了解释器锁,导致python解释器在同一时刻只能解释一个线程,
所以大大降低了python的执行效率
后果:python线程一般会用在存在大量阻塞的IO 程序或者高延迟的IO程序中(网络消息收发)
因为python线程在遇到阻塞时会主动让出解释器
GIL建议解决:
*尽量使用进程完成并发
*不使用c作为解释器 用java c#
* 可以使用多种组合的并发方案