今日内容:
1.守护进程
守护 就是看着 陪着
在代码中 进程只能由进程类守护
一个进程守护者另一个进程 指的是两个进程之间的关联关系
特点:守护进程(妃子)在被守护进程(皇帝)死亡时 会跟随被守护进程死亡
守护进程能不能先死?
安卓系统中有大量的时候进程 负责维护连接
2.互斥锁*****
3.IPC
4.生产者消费者模型******
1.守护进程:
def task(): print("妃子 升级为皇后") time.sleep(3) print("皇后 挂了") if __name__ == '__main__': p = Process(target=task) 将这个子进程设置为当前进程守护进程 p.daemon = True p.start() print("崇祯登基") print("崇祯驾崩了....") 守护进程的代码非常简单 """ p.daemon = True 注意必须在启动进程之前执行
什么守护需要使用守护进程
例如:qq中有个下载视频 应该用子进程去做 但是 下载的过程中 qq退出 那么下载也没必要继续了
使用场景不多 了解即可
2.互斥锁:
from multiprocessing import Process,Lock 进程间 内存空间是相互独立的 def task1(lock): lock.acquire() for i in range(10000): print("===") lock.release() def task2(lock): lock.acquire() for i in range(10000): print("===============") lock.release() def task3(lock): lock.acquire() for i in range(10000): print("======================================") lock.release() if __name__ == '__main__': 买了一把锁 mutex = Lock() for i in range(10): p = Process(target=) p1 = Process(target=task1,args=(mutex,)) p2 = Process(target=task2,args=(mutex,)) p3 = Process(target=task3,args=(mutex,)) p1.start() p1.join() p2.start() p2.join() p3.start() p3.join() p1.start() p2.start() p3.start() print("over!")
什么时候用锁?
当多个进程 同时读写一份数据 数据很可能就会被搞坏
第一个进程写了一个中文字符的一个字节 CPU被切换到另一个进程
另一个进程也写了一中文字符的一个字节
最后文件解码失败
问题之所以出现 是因为并发 无法控制顺序
目前可以使用join来将所有进程并发改为串行
与join的区别?
多个进程并发的访问了同一个资源 将导致资源竞争(同时读取不会产生问题 同时修改才会出问题)
第一个发案 加上join 但是这样就导致了 不公平 相当于 上厕所得按照颜值来
第二个发案 加锁 谁先抢到资源谁先处理
相同点:都变成了 串行
不同点:
1.join顺序固定 锁顺序不固定!!!
2.join使整个进程的任务全部串行二锁可以指定哪些代码要串行
锁使用什么?
锁本质上就是一个bool类型的标识符 大家(多个进程)在执行任务之前先判断标识符
互斥锁 两个进程相互排斥
注意 要想锁住注意必须保证 大家拿到锁是同一把
怎么使用?
在需要加锁的地方lock.acquire() 表示锁定
在代码执行完后一定要lock.release()表示释放锁
lock.acquire()
放需要竞争资源的代码 (同时写入数据)
lock.release()
抢票:
抢票!!!
多个用户在同时读写同一个数据
rom multiprocessing import Process,Lock import json,time,random 查看余票 def show_ticket(name): time.sleep(random.randint(1,3)) with open(r"ticket.json","rt",encoding="utf-8") as f: dic = json.load(f) print("%s查看 剩余票数:%s" % (name ,dic["count"])) 购买票 def buy_ticket(name): # 购买前再次查询 with open(r"ticket.json", "rt", encoding="utf-8") as f: # 修改数据 dic = json.load(f) if dic["count"] > 0: dic["count"] -= 1 # 模拟网络延迟 time.sleep(random.randint(1,3)) # 模拟服务器收到数据 写入文件 with open(r"ticket.json", "wt", encoding="utf-8") as f2: json.dump(dic,f2) print("%s 购票成功!" % name) def task(lock,name): 查看余票可以并发执行 不需要锁住 show_ticket(name) 购票的操作需要锁 因为设涉及到同时修改数据 lock.acquire() buy_ticket(name) lock.release() if __name__ == '__main__': 买个锁 mutex = Lock() for i in range(11): p = Process(target=task,args=(mutex,"客户%s" % i)) p.start()
查询票这个事情 可以多个进程同时执行
但是买票这个过程 不能同时进行 前一个没买完 后一个就不能买
4.进程间通讯:
IPC指的是进程间通讯
之所以开启子进程 肯定需要他帮我们完成任务 很多情况下 需要将数据返回给父进程
然后 进程内存是物理隔离的
解决发案:
1.将共享数据放到文件中 就是慢
2.管理 subprocess中的那个 管道只能单向通讯 必须存在父子关系
3.共享一块内存区域 得操作帮你分配 速度快
om multiprocessing import Process,Manager import time def task(dic): print("子进程xxxxx") # li[0] = 1 # print(li[0]) dic["name"] = "xx" if __name__ == '__main__': m = Manager() li = m.list([100]) dic = m.dict({}) 开启子进程 p = Process(target=task,args=(dic,)) p.start() time.sleep(3) print(dic)
进程间通讯2:
进程间通讯的另一种方式 使用queue queue 队列 队列的特点: 先进的先出 后进后出 就像扶梯 from multiprocessing import Process,Queue 基础操作 必须要掌握的 创建一个队列 q = Queue() 存入数据 q.put("hello") q.put(["1","2","3"]) q.put(1) 取出数据 print(q.get()) print(q.get()) print(q.get()) print(q.get()) 阻塞操作 必须掌握 q = Queue(3) 存入数据 q.put("hello",block=False) q.put(["1","2","3"],block=False) q.put(1,block=False) 当容量满的时候 再执行put 默认会阻塞直到执行力了get为止 如果修改block=False 直接报错 因为没地方放了 q.put({},block=False) 取出数据 print(q.get(block=False)) print(q.get(block=False)) print(q.get(block=False)) 对于get 当队列中中没有数据时默认是阻塞的 直达执行了put 如果修改block=False 直接报错 因为没数据可取了 print(q.get(block=False)) 了解 q = Queue(3) q.put("q",timeout=3) q.put("q2",timeout=3) q.put("q3",timeout=3) 如果满了 愿意等3秒 如果3秒后还存不进去 就炸 q.put("q4",timeout=3) print(q.get(timeout=3)) print(q.get(timeout=3)) print(q.get(timeout=3)) 如果没了 愿意等3秒 如果3秒后还取不到数据 就炸 print(q.get(timeout=3))
ticket.json:
{"conut":1}