python全栈开发基础第二十一篇互斥锁以及进程之间的三种通信方式(IPC)以及生产者个消费者模型

Posted xiaohema

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python全栈开发基础第二十一篇互斥锁以及进程之间的三种通信方式(IPC)以及生产者个消费者模型相关的知识,希望对你有一定的参考价值。

一、互斥锁

进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理。

注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行的修改,没错,速度是慢了,牺牲了速度而保证了数据安全。

1.上厕所的小例子:你上厕所的时候肯定得锁门吧,有人来了看见门锁着,就会在外面等着,等你吧门开开出来的时候,下一个人才去上厕所。

from multiprocessing import Process,Lock
import os
import time
def work(mutex):
    mutex.acquire()
    print(‘task[%s] 上厕所‘%os.getpid())
    time.sleep(3)
    print(‘task[%s] 上完厕所‘%os.getpid())
    mutex.release()
if __name__ == ‘__main__‘:
    mutex = Lock()
    p1 = Process(target=work,args=(mutex,))
    p2 = Process(target=work,args=(mutex,))
    p3 = Process(target=work,args=(mutex,))
    p1.start()
    p2.start()
    p3.start()
    p1.join()
    p2.join()
    p3.join()
    print(‘主‘)

2.模拟抢票(也是利用了互斥锁的原理  :LOCK互斥锁)

import json
import time
import random
import os
from multiprocessing import Process,Lock
def chakan():
    dic = json.load(open(‘piao‘,))  # 先查看票数,也就是打开那个文件
    print(‘剩余票数:%s‘ % dic[‘count‘])  # 查看剩余的票数
def buy():
    dic = json.load(open(‘piao‘,))
    if dic[‘count‘]>0: #如果还有票
        dic[‘count‘]-=1 #就修改里面的值-1
        time.sleep(random.randint(1,3)) #执行里面买票的一系列操作就先不执行了,让睡一会代替(并且随机的睡)
        json.dump(dic,open(‘piao‘,‘w‘))
        print(‘%s 购票成功‘ % os.getpid())  # 当前的那个id购票成功
def task(mutex): #抢票
    chakan()  #因为查看的时候大家都可以看到,不需要加锁
    mutex.acquire() #加锁
    buy() #买的时候必须一个一个的买,先等一个人买完了,后面的人在买
    mutex.release() #取消锁
if __name__ == ‘__main__‘:
    mutex = Lock()
    for i in range(50):#让50个人去访问那个票数
        p = Process(target=task,args=(mutex,))
        p.start()

  

二、Process对象的其他属性

p.daemon :守护进程(必须在开启之前设置守护进程):如果父进程死,子进程p也死了

p.join:父进程等p执行完了才运行主进程,是父进程阻塞在原地,而p仍然在后台运行。

terminate:强制关闭。(确保p里面没有其他子进程的时候关闭,如果里面有子进程,你去用这个方法强制关闭了就会产生僵尸进程(打个比方:如果你老子挂了,你还没挂,那么就没人给你收尸了,啊哈哈))

is_alive:关闭进程的时候,不会立即关闭,所以is_alive立刻查看的结果可能还是存活

p.join():父进程在等p的结束,是父进程阻塞在原地,而p仍然在后台运行

p.name:查看名字

p.pid :查看id

我们可以简单介绍一下僵尸进程:

子进程运行完成,但是父进程迟迟没有进行回收,此时子进程实际上并没有退出,其仍然占用着系统资源,这样的?进程称为僵尸进程

因为僵尸进程的资源一直未被回收,造成了系统资源的浪费,过多的僵尸进程将造成系统性能下降,所以应避免出现僵尸进程。

from multiprocessing import Process
import os
import time
def work():
    print(‘%s is working‘%os.getpid())
    time.sleep(3)
if __name__ == ‘__main__‘:
    p1 =Process(target=work)
    p2 =Process(target=work)
    p3 =Process(target=work)
    # p1.daemon = True
    # p2.daemon = True #守护进程(守护他爹)
    # p3.daemon = True  #主进程死了子进程也死了(就不会执行子进程了)
    p1.start()
    p2.start()
    p3.start()

    p3.join()
    p2.join()
    p1.join() #多个join就是在等花费时间最长的那个运行完就执行主程序了
    print(‘主程序‘)

# -了解方法---------------
#     p1.terminate()  #强制关闭进程
#     time.sleep(3)
#     print(p1.is_alive())  #看是不是还活着
#     print(p1.name) #查看进程名字
#     print(p1.pid) #查看id号
#     print(‘主程序‘)

 

 

三、进程间的三种通信(IPC)方式:

方式一:队列(推荐使用)

进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的

1.队列:队列类似于一条管道,元素先进先出
需要注意的一点是:队列都是在内存中操作,进程退出,队列清空,另外,队列也是一个阻塞的形态
2.队列分类
队列有很多种,但都依赖与模块queue
queue.Queue() #先进先出
queue.LifoQueue() #后进先出
queue.PriorityQueue() #优先级队列
queue.deque() #双线队列

创建队列的类(底层就是以管道和锁定的方式实现):

Queue([maxsize]):创建共享的进程队列,Queue是多进程安全的队列,
可以使用Queue实现多进程之间的数据传递。

参数介绍:

 maxsize是队列中允许最大项数,省略则无大小限制。

方法介绍:

q.put方法用以插入数据到队列中,put方法还有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,该方法会阻塞timeout指定的时间,直到该队列有剩余的空间。如果超时,会抛出Queue.Full异常。如果blocked为False,但该Queue已满,会立即抛出Queue.Full异常。
q.get方法可以从队列读取并且删除一个元素。同样,get方法有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,那么在等待时间内没有取到任何元素,会抛出Queue.Empty异常。如果blocked为False,有两种情况存在,如果Queue有一个值可用,则立即返回该值,否则,如果队列为空,则立即抛出Queue.Empty异常.
  
q.get_nowait():同q.get(False)
q.put_nowait():同q.put(False)
 
q.empty():调用此方法时q为空则返回True,该结果不可靠,比如在返回True的过程中,如果队列中又加入了项目。
q.full():调用此方法时q已满则返回True,该结果不可靠,比如在返回True的过程中,如果队列中的项目被取走。
q.qsize():返回队列中目前项目的正确数量,结果也不可靠,理由同q.empty()和q.full()一样

应用:

#队列

# 1.可以往队列里放任意类型的
# 2.先进先出
from multiprocessing import Process,Queue
q= Queue(3)
q.put(‘first‘)  #默认block=True
q.put(‘second‘)
q.put(‘third‘)

print(q.get())
print(q.get())
print(q.get())

  

 

以上是关于python全栈开发基础第二十一篇互斥锁以及进程之间的三种通信方式(IPC)以及生产者个消费者模型的主要内容,如果未能解决你的问题,请参考以下文章

Python开发第二十一篇:Web框架之Django基础

Python开发第二十一篇:Web框架之Django基础

Python从入门到精通(二十一)Python并发编程互斥锁的运用以及线程通信

python全栈开发基础第二十三篇线程

python全栈开发基础第二十二篇进程池和回调函数

python全栈开发基础第二十篇利用multiprocessing模块开进程