进程的其他方法:
pid:查看进程号
name:查看进程名
is_alive():产看进程是否还活着
terminate():给操作系统发送一个结束进程的信号
守护进程:
P.daemon = true
设置为守护进程,主进程代码运行完毕被设置为守护的子进程会随之结束
孤儿进程、僵尸进程(了解)
锁:保证数据安全,牺牲了效率:加锁的这段代码使进程变成了串行执行状态;多进程同时使用数据,会导致数据不安全
l= Lock()
一。with l:
pass
二。
l.acquire()
pass
l.release()
队列:
Queue()
q=Queue(10)
q.put() 放数据
q.get() 取数据
q.size()返回当前队列长度
消费者生产者模型:缓冲用,解耦用,防止通行的一方卡住
示例一:缺点多个结束信号不科学
1 from multiprocessing import Process,Queue 2 import time 3 4 def produce(q): 5 for i in range(10): 6 time.sleep(0.2) 7 s = '%s号包子'%i 8 q.put(s) 9 print(s+'中了') 10 q.put(None) 11 12 def consumer(q): 13 while 1: 14 time.sleep(0.5) 15 num = q.get() 16 if num == None: 17 print('吃完了,海量啊') 18 break 19 print('%s被吃了'%num) 20 21 if __name__ == '__main__': 22 q = Queue(10) 23 pro = Process(target=produce,args=(q,)) 24 con = Process(target=consumer,args=(q,)) 25 26 pro.start() 27 con.start() 28 29 # 模拟了一个生产者与一个消费者的过程,可以自动结束 30 # 但是通过发结束信号来终止的方式在面对多个消费者时不方便。
示例2:改进,使用Joinablequeue
q.task_done() #给队伍返回一个任务处理完毕的信号
q.join() #等待放入队列中的任务全部执行完毕,即上面的数量等于放入队列中的所有数量,在此之前,阻塞
1 from multiprocessing import Process,Queue,JoinableQueue 2 import time 3 4 def produce(q): 5 for i in range(10): 6 time.sleep(0.2) 7 s = '%s号包子'%i 8 q.put(s) 9 print(s+'中了') 10 q.join() 11 12 def consumer(q): 13 while 1: 14 time.sleep(0.5) 15 num = q.get() 16 print('%s被吃了'%num) 17 q.task_done() 18 19 if __name__ == '__main__': 20 q = JoinableQueue(10) 21 pro = Process(target=produce,args=(q,)) 22 con = Process(target=consumer,args=(q,)) 23 24 pro.start() 25 con.daemon = True #设置为守护进程,以便在主程序结束的时候可以结束这个while循环的子进程 26 con.start() 27 28 pro.join() #等到生产者运行结束,生产者结束的标志是被取走的任务与放入的相同,即此时队列为空 29 print('主程序运行结束') 30 31 #即使多个消费者,此时也不需要再重复发送结束信号。此时需要明确两个join的不同作用以及准确的守护进程设置 32 # consumer()是一个while循环,不会结束。 produce()运行结束时队列为空,程序功能实现, 33 # 因此必须等consumer()执行结束,才可以结束主程序,避免守护进程被提钱杀死。
进程数据共享
1 from multiprocessing import Process,Manager,Lock 2 import time 3 def f1(m_d): 4 temp = m_d['num'] 5 temp -= 1 6 m_d['num'] = temp 7 8 if __name__ == '__main__': 9 m = Manager() 10 m_d = m.dict({'num':100}) 11 p_list = [] 12 for i in range(10): 13 p = Process(target=f1,args=(m_d,)) 14 p.start() 15 p_list.append(p) 16 for p in p_list: 17 p.join() 18 19 print(m_d['num']) 20 21 22 #此时,数据通信正常,但是如果操作需要时间,就会导致出问题,后面进程拿到的数据可能是之前没有处理完的。 23 #为解决之,加锁 24 def f1(m_d,lic): 25 lic.acquire() 26 temp = m_d['num'] 27 temp -= 1 28 time.sleep(1) 29 m_d['num'] = temp 30 lic.release() 31 if __name__ == '__main__': 32 m = Manager() 33 m_d = m.dict({'num':100}) 34 p_list = [] 35 lic = Lock() 36 for i in range(10): 37 p = Process(target=f1,args=(m_d,lic)) 38 p.start() 39 p_list.append(p) 40 for p in p_list: 41 p.join() 42 43 print(m_d['num']) 44 45 #加锁之后,保证不论时间多久,前一个子进程在释放锁之后,后面的子进程才会执行锁内的代码,降低了效率
锁的应用之抢票模型
1 from multiprocessing import Process,Lock 2 import time 3 def search_ticket(i): 4 with open('ticket','r',encoding='utf-8') as f: 5 num_txt = f.read() 6 num_dict = eval(num_txt) 7 return num_dict 8 9 def show_ticket(i): 10 print('%s号查询到的剩余票数为%s'%(i,search_ticket(i)['ticket'])) 11 12 def get_ticket(i,lic): 13 lic.acquire() 14 num_ticket = search_ticket(i) 15 if num_ticket['ticket'] > 0: 16 print('%s号抢到了'%i) 17 num_ticket['ticket'] -= 1 18 with open('ticket', 'w', encoding='utf-8') as f: 19 f.write(str(num_ticket)) 20 else: 21 print('%s号没抢到'%i) 22 lic.release() 23 24 if __name__ == '__main__': 25 for i in range(1,11): 26 p1 = Process(target=show_ticket,args=(i,)) 27 p1.start() 28 lic = Lock() 29 for i in range(1,11): 30 p2 = Process(target=get_ticket,args=(i,lic)) 31 p2.start() 32 33 #锁的作用是锁定结束前抢到的人执行至锁释放,然后其余人也竞争,每一轮都相同