标签:共享数据 进程创建 dump queue range 将不 修改 通信 进程同步
multiprocessing 模块介绍
python中的多线程无法利用多核优势,如果想要充分的使用多核cpu的资源,os.cpu_count可以查看逻辑cpu数,在python中大部分情况需要使用多进程,python提供了multiprocessing
muliprocessing模块用来开启子进程,并在子进程中执行我们制定的任务(比如函数),这个模块与多
线程模块threading编程接口类似
multiprocessing模块的功能众多,支持子进程,通信和共享数据,执行不同形式的同步,提供了Process,Queue,Pipe,Lock等组件
multiprocessing与线程不同的是进程没有任何共享状态,进程修改数据仅限于该进程内
Process类
Process(group,target=func,name=str,args(x,),kwargs={‘num‘:1,})
由该类实例化得到的对象,表示一个子进程中的任务
强调:需要使用关键字的方式来给Process传参数
args指定的为target对应的函数传位置参数,是元组形式,括号类必须有逗号
参数介绍:
1 group参数未使用,值始终为None 2 3 target表示调用对象,即子进程要执行的任务 4 5 args表示调用对象的位置参数元组,args=(1,2,‘egon‘,) 6 7 kwargs表示调用对象的字典,kwargs={‘name‘:‘egon‘,‘age‘:18} 8 9 name为子进程的名称
方法介绍:
1.P.start()启动进程,并调用该子进程中的P.run()
2.P.run()进程启动时运行的方法,他去调用target指定的函数,我们在自定义/继承与Process的类总一定要实现run()这个方法
3.P.terminate()强制终止进程p,不会进行任何清理操作,如果p创建了子进程,那么这个子进程就成了僵尸进程
使用该方法需要特别小心这种情况,如果p还保存了一个锁那么也将不会被释放,进而导致死锁
4.P.is_alive()如果p任然在运行,那么返回True
5.P.join([timeout])主线程序等待p终止(强调,是主线程序处于等待状态,p处于运行状态),timeout是可选的
超时时间,P.join()只能join住start开启的进程,放在start()下边,而不能join住run开启的进程
属性介绍:
p.deamon,默认值为False,如果设为True,代表p为后台运行的守护进程,当p父进程终止时,p也随之终止,并且
设定为True后,p不能创建自己的新进程,p.deamon必须在p.start()之前设置
p.name进程的名称
p.pid进程的id
process类的使用
在windo中process()必须放到if__name__==‘__main__‘:下去运行,不会在导入时被调用
由于window没有fork,多处理模块启动一个新的python进程并导入调用模块
如果在导入时调用process(),name这将启动无限继承的新进程(或直到机器耗尽资源)
创建并开启子进程的两种方式
#开进程的方法一:
import time
import random
from multiprocessing import Process
def piao(name):
print(‘%s piaoing‘ %name)
time.sleep(random.randrange(1,5))
print(‘%s piao end‘ %name)
p1=Process(target=piao,args=(‘egon‘,)) #必须加,号
p2=Process(target=piao,args=(‘alex‘,))
p3=Process(target=piao,args=(‘wupeqi‘,))
p4=Process(target=piao,args=(‘yuanhao‘,))
p1.start()
p2.start()
p3.start()
p4.start()
print(‘主线程‘)
方法一
#开进程的方法二:
import time
import random
from multiprocessing import Process
class Piao(Process):
def __init__(self,name):
super().__init__()
self.name=name
def run(self):
print(‘%s piaoing‘ %self.name)
time.sleep(random.randrange(1,5))
print(‘%s piao end‘ %self.name)
p1=Piao(‘egon‘)
p2=Piao(‘alex‘)
p3=Piao(‘wupeiqi‘)
p4=Piao(‘yuanhao‘)
p1.start() #start会自动调用run
p2.start()
p3.start()
p4.start()
print(‘主线程‘)
方法二
进程直接的内存空间是隔离的
守护进程
主进程创建守护进程
其一:守护进程会在主进程代码执行结束后就终止
其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes are not allowed to have children
注意:进程之间是互相独立的,主进程代码运行结束,守护进程随即终止
from multiprocessing import Process
import time
import random
class Piao(Process):
def __init__(self,name):
self.name=name
super().__init__()
def run(self):
print(‘%s is piaoing‘ %self.name)
time.sleep(random.randrange(1,3))
print(‘%s is piao end‘ %self.name)
p=Piao(‘egon‘)
p.daemon=True #一定要在p.start()前设置,设置p为守护进程,禁止p创建子进程,并且父进程代码执行结束,p即终止运行
p.start()
print(‘主‘)
进程同步(锁)
进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,
而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理
#文件db的内容为:{"count":1}
#注意一定要用双引号,不然json无法识别
from multiprocessing import Process,Lock
import time,json,random
def search():
dic=json.load(open(‘db.txt‘))
print(‘\033[43m剩余票数%s\033[0m‘ %dic[‘count‘])
def get():
dic=json.load(open(‘db.txt‘))
time.sleep(0.1) #模拟读数据的网络延迟
if dic[‘count‘] >0:
dic[‘count‘]-=1
time.sleep(0.2) #模拟写数据的网络延迟
json.dump(dic,open(‘db.txt‘,‘w‘))
print(‘\033[43m购票成功\033[0m‘)
def task(lock):
search()
lock.acquire()
get()
lock.release()
if __name__ == ‘__main__‘:
lock=Lock()
for i in range(100): #模拟并发100个客户端抢票
p=Process(target=task,args=(lock,))
p.start()
加锁:购票行为由并发变成了串行,牺牲了运行效率,但保证了数据安全
#加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改,没错,速度是慢了,但牺牲了速度却保证了数据安全。 虽然可以用文件共享数据实现进程间通信,但问题是: 1.效率低(共享数据基于文件,而文件是硬盘上的数据) 2.需要自己加锁处理
标签:共享数据 进程创建 dump queue range 将不 修改 通信 进程同步
原文地址:https://www.cnblogs.com/fushaunglin/p/9594532.html