主要内容:
# Process
# 1.进程之间的数据隔离问题# 2.守护进程# 几个进程的模型 ---- 进程同步的工具
# 有先后顺序 就是同步 # 进程之间 就是异步 # 希望原本异步的多进程操作,维持一个顺序 -- 同步工具# 3.锁 Lock *****# 4.信号量 Semaphore ***# 5.事件 Event **
1.进程之间的数据隔离问题
from multiprocessing import Processn = 100def fun(): global n n -= 1 return nif __name__ == '__main__': p = Process(target=fun) p.start() print(n)"""# 进程与进程之间的数据是隔离的# 内存空间是不能共享的# 所以要想进行通信,必须借助其他手段# 且这两个进程都是自愿的# 子进程的执行结果父进程获取不到# 父进程依赖子进程的执行结果呢# 父进程如何获取子进程的执行结果??? # 父子进程之间通过socket通信"""
2.守护进程
# 设置成守护进程之后 会有什么效果呢?
# 守护进程会在主进程的代码执行完毕之后直接结束,无论守护进程是否执行完毕from multiprocessing import Processimport timedef fun(): print("start") time.sleep(3) print("这是一个好天气")if __name__ == '__main__': p = Process(target=fun) p.daemon = True # 守护进程的属性,默认是False,如果设置成True,就表示设置这个子进程为一个守护进程 # 设置守护进程的操作应该在开启子进程之前 p.start() time.sleep(1) print("主进程结束了!") # 设置成守护进程之后 会有什么效果呢? # 守护进程会在主进程的代码执行完毕之后直接结束,无论守护进程是否执行完毕
关于守护进程的一个需要注意的点,示例如下:(注意下面的fun2里面的in fun2只运行了两次,是跟随主函数的)
import timefrom multiprocessing import Processdef fun(): print("start") time.sleep(3) print("今天天气不错")def fun2(): while True: print("in fun2") time.sleep(0.5)if __name__ == '__main__': p = Process(target=fun) p.start() p = Process(target=fun2) p.daemon = True p.start() time.sleep(1) print("主程序结束了")"""运行结果如下:in fun2startin fun2主程序结束了今天天气不错"""
守扩应用主要有如下功能.:
# 报活 主进程还活着 # 100台机器 100个进程 10000进程 # 应用是否在正常工作 - 任务管理器来查看 # 守护进程如何向监测机制报活???send/写数据库 # 为什么要用守护进程来报活呢?为什么不用主进程来工作呢??? # 守护进程报活几乎不占用CPU,也不需要操作系统去调度 # 主进程能不能严格的每60s就发送一条信息
下面是多进程起socket的实例:
import socket from multiprocessing import Process def fun(conn): try: while 1: ret = conn.recv(1024) print(ret) conn.send(b"hi") except ConnectionAbortedError: pass finally: conn.close() if __name__ == '__main__': sk = socket.socket() ip_addr=("127.0.0.1",9000) sk.bind(ip_addr) sk.listen() try: while True: conn,addr = sk.accept() Process(target=fun,args=(conn,)).start() finally: sk.close()
锁:
# 锁
# lock = Lock() # 创造了一把锁# lock.acquire() # 获取了这把锁的钥匙# lock.release() # 归还这把锁的钥匙锁的示例:
import time,jsonfrom multiprocessing import Lockfrom multiprocessing import Processdef search(i): with open("db","r") as f :content = json.load(f) time.sleep(0.2) print("第%s个用户正在查看,还剩%s个票"%(i,content["count"]))def buy(i): with open("db","r") as f :content = json.load(f) time.sleep(0.2) print("第%s个用户正在查看,还剩%s个票"%(i,content["count"])) if content["count"] > 0: print("第%s个用户购票成功!"%i) content["count"] -= 1 with open("db","w") as f : json.dump(content,f)def test(i,lock): search(i) lock.acquire() buy(i) lock.release()if __name__ == '__main__': lock = Lock() # lock.acquire() # lock. for i in range(10): Process(target=test,args=(i,lock)).start()
# 当多个进程共享一段数据的时候,数据会出现不安全的现象,
# 需要加锁来维护数据的安全性信号量
# 信号量的本质 # 多把钥匙对应一把锁 # lock+count计数
互斥锁同时只允许一个线程更改数据,而信号量Semaphore是同时允许一定数量的线程更改数据 。假设商场里有4个迷你唱吧,所以同时可以进去4个人,如果来了第五个人就要在外面等待,等到有人出来才能再进去玩。实现:信号量同步基于内部计数器,每调用一次acquire(),计数器减1;每调用一次release(),计数器加1.当计数器为0时,acquire()调用被阻塞。这是迪科斯彻(Dijkstra)信号量概念P()和V()的Python实现。信号量同步机制适用于访问像服务器这样的有限资源。信号量与进程池的概念很像,但是要区分开,信号量涉及到加锁的概念
示例代码:
import os,time,randomfrom multiprocessing import Process,Semaphoredef go_ktv(sem,user): sem.acquire() print("%s在ktv中" % user) time.sleep(random.randint(3,10)) print("%s走出了ktv"%user) sem.release()if __name__ == '__main__': sem = Semaphore(2) for i in range(10): Process(target=go_ktv,args=(sem,i)).start()"""# 信号量的本质 # 多把钥匙对应一把锁 # lock+count计数"""
事件:
python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set、wait、clear。 事件处理的机制:全局定义了一个“Flag”,如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞,如果“Flag”值为True,那么event.wait 方法时便不再阻塞。clear:将“Flag”设置为Falseset:将“Flag”设置为True
示例代码:
import timeimport randomfrom multiprocessing import Process,Eventdef ligth(e): print("\033[1;31m 红灯亮\033[0m") while True: time.sleep(2) if e.is_set(): print("\033[1;31m 红灯亮\033[0m") e.clear() else: print("\033[1;32m 绿灯亮\033[0m") e.set()#车 等或者通过def car(id,e): if not e.is_set(): print("car %s等待" %id) e.wait() print("car %s通过"%id)def police_car(id,e): if not e.is_set(): e.wait(timeout=0.5) print("police car %s 通过" % id )#主进程启动交通控制烦,启动车的进程if __name__ == '__main__': e = Event() Process(target=ligth,args=(e,)).start() for i in range(10): Process(target=car,args=(i,e)).start() time.sleep(random.randrange(0, 3, 2))