主要内容:
# Process
# 1.进程之间的数据隔离问题
# 2.守护进程
# 几个进程的模型 ---- 进程同步的工具
# 有先后顺序 就是同步
# 进程之间 就是异步
# 希望原本异步的多进程操作,维持一个顺序 -- 同步工具
# 3.锁 Lock *****
# 4.信号量 Semaphore ***
# 5.事件 Event **
1.进程之间的数据隔离问题
from multiprocessing import Process n = 100 def fun(): global n n -= 1 return n if __name__ == '__main__': p = Process(target=fun) p.start() print(n) """ # 进程与进程之间的数据是隔离的 # 内存空间是不能共享的 # 所以要想进行通信,必须借助其他手段 # 且这两个进程都是自愿的 # 子进程的执行结果父进程获取不到 # 父进程依赖子进程的执行结果呢 # 父进程如何获取子进程的执行结果??? # 父子进程之间通过socket通信 """
2.守护进程
# 设置成守护进程之后 会有什么效果呢?
# 守护进程会在主进程的代码执行完毕之后直接结束,无论守护进程是否执行完毕
from multiprocessing import Process import time def 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 time from multiprocessing import Process def 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 fun2 start in 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,json from multiprocessing import Lock from multiprocessing import Process def 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,random from multiprocessing import Process,Semaphore def 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”设置为False
set:将“Flag”设置为True
示例代码:
import time import random from multiprocessing import Process,Event def ligth(e): print("