一:守护进程
# 守护进程:顾名思义,就是一个进程守护着另一个进程,指的是两个进程之间的关系。
# 特点:就是守护进程在被守护进程死亡时,也会跟着被守护进程的死亡而死亡。
使用方法:
from multiprocessing import Process
import time
def task():
print('hello')
time.sleep(3)
print('see u')
if __name__ == '__main__':
p = Process(target = task)
p.daemon = True
p.start()
time.sleep(3) #
print('process is running')
# 1.daemon必须在start之前写
# 2.当主进程死亡时,守护进程也会死亡,如果注释掉time.sleep(3),守护进程还没来得及执 行就死亡。
二:互斥锁
#当多个进程对统一资源进行读写时,这些进程会对这个资源产生竞争,从而导致数据错乱,解决方法就是将这些进程变成串行。那么我们可以用下面的办法来解决:
1.join #把整个进程变成串行,并且顺序是固定的。
# 虽然join可以将进程变成串行,但是串行是顺序是我们人为固定的,对于这些竞争的进程来说不公# 平,而且,当我们需要部分串行的时候,整个时候join显然不是很适用
# 那么由此产生了另一种办法
2.互斥锁 # 可以实现并程中的部分串行,
使用方法
from multiprocessing import Process,Lock
def task1(lock):
lock.acquire()
for i in range(10000):
print('===')
def task2(lock):
lock.acquire()
for i in range(10000):
print("===============")
lock.release()
def task3(lock):
lock.acquire()
for i in range(10000):
print("======================================")
lock.release()
if __name__ == '__main__':
mutex = lock()
p1 = Process(target=task1,args=(mutex,))
p2 = Process(target=task2,args=(mutex,))
p3 = Process(target=task3,args=(mutex,))
p1.start()
p2.start()
p3.start()
print('over')
# 1.先导入模块Lock
# 2.创建一个锁对象 mutex = Lock()
# 3.将进程竞争的资源上锁
注意:所有的进程上锁的话必须使用同一把锁
三:互斥锁应用
抢票程序
from multiprocessing import Process,Lock
import json,time,random
# file = {"count":1} # json 格式
def show_ticket(name):
# 模拟网络延迟
time.sleep(random.randint(1,5))
with open ('filename','rt',encoding = 'utf-8') as f:
data = json.load(f)
print('%s查看了车票剩余:%s' %(name,data['count']))
def buy_ticket(name):
with open ('filename','rt',encoding = 'utf-8') as f:
data = json.load(f)
if data['count'] > 0:
data['count'] -=1
time.sleep(random.randint(1,3))
time.sleep(random.randint(1,3))
with open('filename','wt',encoding = 'utf-8') as f1:
json.dump(data,f1)
print('%s购票成功' %name)
def task(lock,name):
show_ticket(name)
lock.acquire()
buy_ticket(name)
lock.release()
if __name__ == '__main__':
lock = Lock()
for i in range(1,11):
p = Process(target = task,args = (lock,'客户%s' %i))
p.start()
四:ipc
# 进程彼此之间互相隔离,要实现进程间通信(ipc/inter process commucation),
# multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的
创建队列的类(底层就是以管道和锁定的方式实现的):
# Queue([maxsize]):创建共享进程队列,Queue是多进程安全的队列,可以使用Queue实现多进# 程之间的数据传递
参数介绍
1.maxsize #是队列中允许最大项数,省略则需大小限制
方法一介绍
q = Queue()
1.q.put #方法用以插入数据到队列中,put方法还有两个参数可以选择:blocked和timeout。 # 如果block为True(默认),并且timeout为正值,该方法会阻塞timeout指定的时间,直到 # 该队列有剩余的空间。如果超时,会抛出Queue.Full异常。
# 如果block为False,但是Queue已经满了,会立即抛出Queue.Full异常。
2.q.get #方法可以从队列取走一个元素(注意是取走)。同样有两个方法参数可以选择:block和# timeout.
# 如果blocked为True(默认值),并且timeout为正值,那么在等待时间内没有取到任何元素,# 会抛出Queue.Empty异常。
# 如果blocked为False,有两种情况存在,如果Queue有一个值可用,则立即返回该值,否则,如# 果队列为空,则立即抛出Queue.Empty异常.
3.q.get_nowwait() # 同q.get(False)
4.q.put_nowwait() # 同q.put(False)
5.q.empty() # 调用此方法时q为空则返回True,该结果不可靠,如在返回True的过程中又 添加了项目。
6.q.full() # 调用此方法时q已满则返回True,该结果不可靠,如在返回True的过程中队 列中的项目又被取走了。
7.q.qsize() # 返回队列中目前项目正确数量,结果也不可靠,和上述一致。
举例
from multiprocessing import Queue
# 创建一个队列
q = Queue()
# 存入数据
q.put('hello) # 存入str
q.put(['1','2','3']) # 存入list
q.put(1) # 存入int
# 读出数据
print(q.get())
print(q.get())
print(q.get())
# 阻塞操作
q = Queue(3) # 限制存放数据的个数
# 存入数据
q.put('hello',block = False) # 不阻塞
q.put(['1','2','3'],block = False) # 不阻塞
q.put(1,block =False) # 不阻塞
# 此时再存入一个数据q.put('word',block = False) 则会抛出Queue.Full异常
# 如果是q.put('word',block = True)则不会抛出异常,会等到Queue有位置后再存入
# 取出数据
print(q.get(block=False))
print(q.get(block=False))
print(q.get(block=False))
# 此时再取出一个数据print(q.get(block = False)) 则会抛出Queue.Empty异常
# 如果是print(q.gte(block = True)则不会抛出异常,会等到Queue有数据后再取走
方法二:
# 导入Manager模块
from multiprocessing import Process,Manager
import time
def task(dic):
print('subprocess is running')
li[0] = 1
print(li)
if __name__ == "__main__":
m = Manager()
# 创建一个公共区域
li = m.list([100])
p = Process(target = task,args = (li,))
p.start()
time.sleep(3)
print(li)
# m = Manager()只能创建list和dict,其他类型则共享不了