并发编程 07.03
1.守护进程
主进程创建守护进程
- 守护进程会在主进程代码执行结束后就终止
- 守护进程内无法再开启子进程,否则会抛出异常
进程之间是相互独立的,主进程代码运行结束,守护进程随即终止
from multiprocessing import Process
import time
def task():
print('The_child_process is run')
time.sleep(3)
print('The_child_process is over')
if __name__ == '__main__':
p = Process(target=task)
p.daemon = True #一定要在p.start()前设置,设置p为守护进程,禁止p创建子进程,并且父进程代码执行结束,p即终止运行
p.start()
print('The main process is run')
time.sleep(3)
print('The main process is over')
2.进程安全问题
#并发运行,效率高,但竞争同一打印终端,带来了打印错乱
from multiprocessing import Process
def task1():
for i in range(1000):
print(1)
for i in range(1000):
print('--------name is nick')
print('--------height is 1.7' )
print('--------weight is 60')
def task2():
for i in range(1000):
print(2)
for i in range(1000):
print('++++++++name is bgon')
print('++++++++height is 1.65')
print('++++++++weight is 70')
if __name__ == '__main__':
p1 = Process(target=task1)
p2 = Process(target=task2)
p1.start()
p1.join()
p2.start()
3.互斥锁
进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,
而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理
#由并发变成了串行,牺牲了运行效率,但避免了竞争
from multiprocessing import Process, Lock
import time,randomdef task1(mutex):
for i in range(1000):
print(1)
mutex.acquire() #加锁
time.sleep(random.random())
print("-------name is nick")
time.sleep(random.random())
print("-------gender is girl") time.sleep(random.random())
print("-------age is 18")
mutex.release() #解锁
def task2(mutex):
for i in range(10000):
print(2)
mutex.acquire() #加锁
time.sleep(random.random())
print("++++++++name is bgon")
time.sleep(random.random())
print("++++++++gender is oldman") time.sleep(random.random())
print("++++++++age is 48")
mutex.release() #解锁if __name__ == '__main__':
mutex = Lock()
print('the locked is created')
p1 = Process(target=task1,args=(mutex,))
p2 = Process(target=task2, args=(mutex,))
p1.start()
p2.start()
4.锁的原理
def task():
global lock
if lock == False:
lock = True
open('.txt','wt')
lock = False
#加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改,没错,速度是慢了,但牺牲了速度却保证了数据安全。
虽然可以用文件共享数据实现进程间通信,但问题是:
1.效率低(共享数据基于文件,而文件是硬盘上的数据)
2.需要自己加锁处理
#因此我们最好找寻一种解决方案能够兼顾:1、效率高(多个进程共享一块内存的数据)2、帮我们处理好锁问题。这就是mutiprocessing模块为我们提供的基于消息的IPC通信机制:队列和管道。
1 队列和管道都是将数据存放于内存中
2 队列又是基于(管道+锁)实现的,可以让我们从复杂的锁问题中解脱出来,
我们应该尽量避免使用共享数据,尽可能使用消息传递和队列,避免处理复杂的同步和锁问题,而且在进程数目增多时,往往可以获得更好的可获展性。
5.锁的案例,模拟抢票
from multiprocess import Process, Lock
import json
def search():
with open('.json') as fr:
data = json.load(fr)
print('The remaining votes',data[''count"])
def get():
with open('.json') as fr:
data =json.load(fr)
if data["count"] > 0:
data["count"] -= 1
with open('.json','wt')as fw:
json.dump(data,fw)
print('buy ticket is successful')
def task(mutex):
search()
mutex.acquire()
get()
mutex.release()
if __name__ == '__main__':
mutex = Lock()
for i in range(5):
p = Process(target=task,args=(mutex,))
p.start()
6.Manager的使用
from multiprocessing import Process,Lock,Manager
import time
def task(data,lock):
lock.acquire()
num = data[0]
time.sleep(0.3)
data[0] = num - 1
lock.release()
print('The_child_process is over')
if __name__ == '__main__':
d = [100]
m = Manager() #创建一个管理器
syncdict = m.list(d) # 让管理器创建一个进程同步的字典
lock = Lock() #创建一个锁
ps = []
for i in range(10):
p = Process(target=task,args=(syncdict,lock))
p.start()
ps.append(p)
for p in ps:
p.join()
print(d)
print(syncdict)
7.进程队列
进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的
from multiprocessing import Quene
q = Quene(2) # 创建队列 并且同时只能存储2个元素
q.put(1)
q.put(2)
# q.put(3,block=True,timeout=3) # 默认是阻塞的 当容器中没有位置了就阻塞 直到有人从里面取走元素为止
print(q.get())
print(q.get())
print(q.get(block=True,timeout=3))# 默认是阻塞的 当容器中没有位置了就阻塞 直到有人存入元素为止
8.函数调用栈
def a():
b()
def b():
c()
def c():
print('c')
raise Exception
a()

浙公网安备 33010602011771号