创建进程的两种方式
方式一:
from multiprocessing import Process import time def test(name): print('%s is running'%name) time.sleep(1) print('%s is over'%name) if __name__ == '__main__': p = Process(target=test,args=('zmm',)) p.start() print("主")
方式二:
from multiprocessing import Process import time class MyProcess(Process): def __init__(self,name): super().__init__() self.name = name def run(self): print('%s is running'%self.name) time.sleep(1) print('%s is over'%self.name) if __name__ == '__main__': p = MyProcess('zmm') p.start()
print('主')
进程对象的join方法
# 父进程等待子进程结束之后在执行 from multiprocessing import Process import time def test(name): print('%s is running'%name) time.sleep(1) print('%s is over'%name) if __name__ == '__main__': p = Process(target=test,args=('zmm',)) p.start() p.join() print('主')
# from multiprocessing import Process # import time # # def task(n): # time.sleep(n) # print('%s is running' %n) # # if __name__ == '__main__': # start_time = time.time() # p1 = Process(target=task,args=(1,)) # p2 = Process(target=task,args=(2,)) # p3 = Process(target=task,args=(3,)) # # 几乎同一个时刻发送三个请求 # p1.start() # p2.start() # p3.start() # # 对着三个自己成使用三个join # # p1.join() # 1s # p2.join() # 2s # p3.join() # 3s # # print(time.time() - start_time,'主进程开始运行....') # 3s 多一点点这是来回切换的所用时间。
验证进程之间的空间隔离
from multiprocessing import Process import time money = 100 def test(): global money money = 10 if __name__ == '__main__': p = Process(target=test) p.start() p.join() print(money) # 100
进程对象及其其他方法
from multiprocessing import Process import time from multiprocessing import Process,current_process import os import time def test(name): # print('%s is running'%name,current_process().pid) print('%s is running'%name,'子进程%s'%os.getpid(),'父进程%s'%os.getppid()) time.sleep(1) print('%s is over'%name) if __name__ == '__main__': p = Process(target=test,args=('zmm',)) p.start() p.terminate() # 杀死当前进程 其实是告诉操作系统帮你杀死一个进程 time.sleep(0.1) print(p.is_alive()) # 判断进程是否存活 # print('主',current_process().pid) print('主',os.getpid(),'主主进程%s'%os.getppid())
守护进程
主进程创建守护进程
其一:守护进程会在主进程代码执行结束后就终止
其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes are not allowed to have children
注意:进程之间是互相独立的,主进程代码运行结束,守护进程随机终止
from multipring import Process import time def test(name): print('%s is running'%name) time.sleep(2) print('%s is over'%name) if __name__ == '__main__': p = Process(target=test,args=('zmm',)) p.daemon=True # 将进程设置为守护进程 这句话必须放在start语句之前 p.start() time.sleep(0.1) print('aaa')
互斥锁
进程之间数据不共享,但是共享同一套文件系统,所以访问同一文件,或同一个打印终端,是没有问题的,而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理
不加锁,效率高但是顺序容易错乱
加锁处理,牺牲了效率,也保证了顺序
上面这种情况虽然使用加锁的形式实现了顺序的执行,但是程序又重新变成串行了,这样确实会浪费了时间,却保证了数据的安全。
接下来,我们以模拟抢票为例,来看看数据安全的重要性。
# data文件
{"ticket":1}
import time import json from multiprocessing import Process,Lock def search(i): with open('data','r',encoding='utf-8') as f: data = f.read() d_t = json.loads(data) print('用户%s查询余票%s'%(i,d_t.get('ticket'))) def buy(i): with open('data','r',encoding='utf-8') as f: data = f.read() d_t = json.loads(data) time.sleep(1) if d_t.get('ticket') > 0: d_t['ticket'] -= 1 with open('data','w',encoding='utf-8') as f: json.dump(d_t,f) print('用户%s抢票成功!'%i) else: print('没票了') def run(i,mutex): search(i) mutex.acquire() buy(i) mutex.release() if __name__ == '__main__': mutex = Lock() for i in range(5): p = Process(target=run,args=(i,mutex)) p.start()
互斥锁
当多个进程操作同一份数据的时候 会造成数据的错乱
这个时候必须加锁处理
将并发变成串行
虽然降低了效率但是提高了数据的安全
注意:
1.锁不要轻易使用 容易造成死锁现象
2.只在处理数据的部分加锁 不要在全局加锁
锁必须在主进程中产生 交给子进程去使用