4月25日 python学习总结 互斥锁 IPC通信 和 生产者消费者模型

一、守护进程  

import random
import time
from multiprocessing import  Process

def task():
    print('name: egon')
    time.sleep(random.randint(0,3))
    print('sex:male')
    time.sleep(random.randint(0, 3))
    print('age:19')


if __name__ == '__main__':
      p=Process(target=task)
      p.daemon()   #将p设置为主进程的守护进程,主进程结束,无论子进程是否正常执行完,都跟主进程一起结束

二、互斥锁

 互斥锁:
强调:必须是lock.acquire()一次,然后 lock.release()释放一次,才能继续lock.acquire(),不能连续的lock.acquire()

 互斥锁vs join的区别:

    大前提:

    二者的原理都是一样,都是将并发变成串行,从而保证有序

 

   区别:

 一、join是按照人为指定的顺序执行,而互斥锁是所以进程平等地竞争,谁先抢到谁执行
 二、 互斥锁可以让一部分代码(修改共享数据的代码)串行,而join只能将代码整体串行

 1 from multiprocessing import Process,Lock
 2 import time,random
 3 
 4 mutex=Lock()
 5 # 互斥锁:
 6 #强调:必须是lock.acquire()一次,然后 lock.release()释放一次,才能继续lock.acquire(),不能连续的lock.acquire()
 7 
 8 # 互斥锁vs join的区别一:
 9 # 大前提:二者的原理都是一样,都是将并发变成串行,从而保证有序
10 # 区别:# 互斥锁vs join的区别:
11 # 大前提:二者的原理都是一样,都是将并发变成串行,从而保证有序
12 # 区别:一、join是按照人为指定的顺序执行,而互斥锁是所以进程平等地竞争,谁先抢到谁执行
13 #    二、 互斥锁可以让一部分代码(修改共享数据的代码)串行,而join只能将代码整体串行
14 
15 def task1(lock):
16     lock.acquire()          #抢锁
17     print('task1:名字是egon')
18     time.sleep(random.randint(1,3))
19     print('task1:性别是male')
20     time.sleep(random.randint(1,3))
21     print('task1:年龄是18')
22     lock.release()          #释放锁
23 
24 def task2(lock):
25     lock.acquire()
26     print('task2:名字是alex')
27     time.sleep(random.randint(1,3))
28     print('task2:性别是male')
29     time.sleep(random.randint(1,3))
30     print('task2:年龄是78')
31     lock.release()
32 
33 
34 def task3(lock):
35     lock.acquire()
36     print('task3:名字是lxx')
37     time.sleep(random.randint(1,3))
38     print('task3:性别是female')
39     time.sleep(random.randint(1,3))
40     print('task3:年龄是30')
41     lock.release()
42 
43 
44 
45 if __name__ == '__main__':
46     p1=Process(target=task1,args=(mutex,))
47     p2=Process(target=task2,args=(mutex,))
48     p3=Process(target=task3,args=(mutex,))
49 
50     # p1.start()
51     # p1.join()
52     # p2.start()
53     # p2.join()
54     # p3.start()
55     # p3.join()
56 
57     p1.start()
58     p2.start()
59     p3.start()
互斥锁应用

 

 1 from multiprocessing import  Process,Lock
 2 import time,json,random,os
 3 
 4 lock=Lock()
 5 def search():
 6     print('========%s 查票======' % os.getpid())
 7     info=json.load(open('test.txt'))
 8     msg='余票为: %s'%info['count']
 9     print(msg)
10 
11 def get(lock):
12     lock.acquire()
13     print('========%s 抢票======'%os.getpid())
14     info = json.load(open('test.txt'))
15     time.sleep(random.random())
16     if info['count']>0:
17         info['count']-=1
18         time.sleep(random.random())
19         json.dump(info,open('test.txt','w'))
20         print('抢票成功')
21     else:
22         print('票已售完')
23     lock.release()
24 
25 def op(lock):
26     search()
27     get(lock)
28 
29 if __name__ == '__main__':
30     for i in range(0,50):
31         p=Process(target=op,args=(lock,))
32         p.start()
模拟抢票系统

 

三、IPC通信(进程之间的的通信控制)  

进程之间通信必须找到一种介质,该介质必须满足

  • 是所有进程共享的
  • 必须是内存空间
  • 附加:帮我们自动处理好锁的问题

1、队列(推荐使用)     

  • 共享的空间
  • 是内存空间
  • 自动帮我们处理好锁定问题

  强调:
     1、队列用来存成进程之间沟通的消息,数据量不应该过大
     2、maxsize的值超过的内存限制就变得毫无意义

from multiprocessing import Queue

q=Queue(3)    #创建队列,并为队列设置大小 此处为3
q.put('first')
q.put({'second':None})      #可以存放任意类型
q.put('')

# q.put(4)      #队列存满,第四个存不进,阻塞,等待别的进程取出队列中内容

print(q.get())
print(q.get())
print(q.get())
print(q.get())   # 阻塞 ,队列为空,取不出东西,等待其他进程往队列中存放东西
p.put('first',block=False,timeout=4)
p.get('first',block=False,timeout=4)

#第一个参数 是存放到队列中的数据
#第二个参数block ,是否进入阻塞状态,当队满存值或队空取值时,默认值为True
#第三个参数timeout ,当队满存值或队空取值时,阻塞等待的时间,若超过时间则报错

 

2、Manager

没有处理好锁问题,不推荐使用 

from multiprocessing import Process,Manager,Lock
import time

mutex=Lock()

def task(dic,lock):
    lock.acquire()
    temp=dic['num']
    time.sleep(0.1)
    dic['num']=temp-1
    lock.release()

if __name__ == '__main__':
    m=Manager()          #创建一个共享空间
    dic=m.dict({'num':10})

    l=[]
    for i in range(10):
        p=Process(target=task,args=(dic,mutex))
        l.append(p)
        p.start()

    for p in l:
        p.join()
    print(dic)

    

  3、管道(不推荐使用)

  • 是所有进程共享的
  • 是内存空间
  • 两头存取数据
  • 没有帮我们自动处理好锁的问题

 

四、生产者消费者模型  

该模型中包含两类重要的角色:

1、生产者:将负责造数据的任务比喻为生产者
2、消费者:接收生产者造出的数据来做进一步的处理,该类人物被比喻成消费者


实现生产者消费者模型三要素

1、生产者
2、消费者
3、队列

什么时候用该模型:

程序中出现明显的两类任何,一类任务是负责生产,另外一类任务是负责处理生产的数据的

该模型的好处:

1、实现了生产者与消费者解耦和
2、平衡了生产力与消费力,即生产者可以一直不停地生产,消费者可以不停地处理,因为二者
不再直接沟通的,而是跟队列沟通

 1 import time
 2 import random
 3 from multiprocessing import Process,Queue
 4 
 5 def consumer(name,q):
 6     while True:
 7         res=q.get()
 8         time.sleep(random.randint(1,3))
 9         print('33[46m消费者===》%s 吃了 %s33[0m' %(name,res))
10 
11 
12 def producer(name,q,food):
13     for i in range(5):
14         time.sleep(random.randint(1,2))
15         res='%s%s' %(food,i)
16         q.put(res)
17         print('33[45m生产者者===》%s 生产了 %s33[0m' %(name,res))
18 
19 
20 if __name__ == '__main__':
21     #1、共享的盆
22     q=Queue()
23 
24     #2、生产者们
25     p1=Process(target=producer,args=('egon',q,'包子'))
26     p2=Process(target=producer,args=('刘清政',q,'泔水'))
27     p3=Process(target=producer,args=('杨军',q,'米饭'))
28 
29     #3、消费者们
30     c1=Process(target=consumer,args=('alex',q))
31     c2=Process(target=consumer,args=('梁书东',q))
32 
33 
34     p1.start()
35     p2.start()
36     p3.start()
37     c1.start()
38     c2.start()
生产者消费者模式
原文地址:https://www.cnblogs.com/95lyj/p/8945183.html