python并发编程之多进程1------互斥锁与进程间的通信

一、互斥锁

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

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

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

  1 from multiprocessing import Process,Lock
  2 import os
  3 import time
  4 def work(mutex):
  5     mutex.acquire()
  6     print(‘task[%s] 上厕所‘%os.getpid())
  7     time.sleep(3)
  8     print(‘task[%s] 上完厕所‘%os.getpid())
  9     mutex.release()
 10 if __name__ == ‘__main__‘:
 11     mutex = Lock()
 12     p1 = Process(target=work,args=(mutex,))
 13     p2 = Process(target=work,args=(mutex,))
 14     p3 = Process(target=work,args=(mutex,))
 15     p1.start()
 16     p2.start()
 17     p3.start()
 18     p1.join()
 19     p2.join()
 20     p3.join()
 21     print(‘主‘)

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

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

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

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

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

  1 from multiprocessing import Process
  2 import os
  3 import time
  4 def work():
  5     print(‘%s is working‘%os.getpid())
  6     time.sleep(3)
  7 if __name__ == ‘__main__‘:
  8     p1 =Process(target=work)
  9     p2 =Process(target=work)
 10     p3 =Process(target=work)
 11     # p1.daemon = True
 12     # p2.daemon = True #守护进程(守护他爹)
 13     # p3.daemon = True  #主进程死了子进程也死了(就不会执行子进程了)
 14     p1.start()
 15     p2.start()
 16     p3.start()
 17
 18     p3.join()
 19     p2.join()
 20     p1.join() #多个join就是在等花费时间最长的那个运行完就执行主程序了
 21     print(‘主程序‘)
 22
 23 # -了解方法---------------
 24 #     p1.terminate()  #强制关闭进程
 25 #     time.sleep(3)
 26 #     print(p1.is_alive())  #看是不是还活着
 27 #     print(p1.name) #查看进程名字
 28 #     print(p1.pid) #查看id号
 29 #     print(‘主程序‘)

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

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

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

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

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

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

应用:

  1 # 1.可以往队列里放任意类型的
  2 # 2.先进先出
  3 from multiprocessing import Process,Queue
  4 q= Queue(3)
  5 q.put(‘first‘)  #默认block=True
  6 q.put(‘second‘)
  7 q.put(‘third‘)
  8
  9 print(q.get())
 10 print(q.get())
 11 print(q.get())
 12
 13 

队列

生产者和消费者模型

在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。

为什么要使用生产者和消费者模式

在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。

什么是生产者消费者模式

生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。

基于队列实现生产者消费者模型

一个生产者和一个消费者(有两种方式)

1、q.put(None):生产者给放一个None进去

  1 from multiprocessing import Process,Queue
  2 import os
  3 import time
  4 import random
  5 #首先得有生产者和消费者
  6 # 生产者制造包子
  7 ‘‘‘这种用 q.put(None)放进去一个None的方法虽然解决了问题
  8 但是如果有多个生产者多个消费者,或许框里面没有包子了但是
  9 还有其他的食物呢,你就已经显示空着,这样也可以解决,就是不完美,
 10 还可以用到JoinableQueue去解决‘‘‘
 11 def producter(q):
 12     for i in range(10):
 13         time.sleep(2) #生产包子得有个过程,就先让睡一会
 14         res = ‘包子%s‘%i #生产了这么多的包子
 15         q.put(res)  #吧生产出来的包子放进框里面去
 16         print(‘\033[44m%s制造了%s\033[0m‘%(os.getpid(),res))
 17     q.put(None) #只有生产者才知道什么时候就生产完了(放一个None进去说明此时已经生产完了)
 18 # 消费者吃包子
 19 def consumer(q):
 20     while True:#假如消费者不断的吃
 21         res = q.get()
 22         if res is None:break #如果吃的时候框里面已经空了,就直接break了
 23         time.sleep(random.randint(1,3))
 24         print(‘\033[41m%s吃了%s\033[0m‘ % (os.getpid(),res))
 25 if __name__ == ‘__main__‘:
 26     q = Queue()
 27     p1 = Process(target=producter,args=(q,))
 28     p2 = Process(target=consumer,args=(q,))
 29     p1.start()
 30     p2.start()
 31     p1.join()
 32     p2.join()  #等待执行完上面的进程,在去执行主
 33     print(‘主‘)
 34
 35 

生产者与消费者1

2、利用JoinableQueue

  1 from multiprocessing import Process,JoinableQueue
  2 import os
  3 import time
  4 import random
  5 #首先得有生产者和消费者
  6 # 消费者吃包子
  7 def consumer(q):
  8     ‘‘‘消费者‘‘‘
  9     while True:#假如消费者不断的吃
 10         res = q.get()
 11         time.sleep(random.randint(1,3))
 12         print(‘\033[41m%s吃了%s\033[0m‘ % (os.getpid(),res))
 13         q.task_done() #任务结束了(消费者告诉生产者,我已经吧东西取走了)
 14 # 生产者制造包子
 15 def producter(q):
 16     ‘‘‘生产者‘‘‘
 17     for i in range(5):
 18         time.sleep(2) #生产包子得有个过程,就先让睡一会
 19         res = ‘包子%s‘%i #生产了这么多的包子
 20         q.put(res)  #吧生产出来的包子放进框里面去
 21         print(‘\033[44m%s制造了%s\033[0m‘%(os.getpid(),res))
 22     q.join()
 23
 24 if __name__ == ‘__main__‘:
 25     q = JoinableQueue()
 26     p1 = Process(target=producter,args=(q,))
 27     p2 = Process(target=consumer,args=(q,))
 28     p2.daemon = True #在启动之前吧消费者设置成守护进程,p1结束了p2也就结束了
 29     p1.start()
 30     p2.start()
 31     p1.join() #在等生产者结束(生产者结束后,就不制造包子了,那消费者一直在吃,就卡住了
 32     #都不生产了还吃啥,就把消费者也结束了  )
 33       #等待执行完上面的进程,在去执行主
 34     print(‘主‘)

生产者与消费者2

多个生产者和多个消费者(有两种方式)

1、q.put(None):生产者给放一个None进去

2、利用JoinableQueue

  1 from multiprocessing import Process,JoinableQueue
  2 import os
  3 import time
  4 import random
  5 #首先得有生产者和消费者
  6 # 消费者吃包子
  7 def consumer(q):
  8     while True:
  9         res = q.get()
 10         time.sleep(random.randint(1,3))
 11         print(‘\033[41m%s吃了%s\033[0m‘ % (os.getpid(),res))
 12         q.task_done() #任务结束了(消费者告诉生产者,我已经吧东西取走了)
 13 def product_baozi(q):
 14     for i in range(5):
 15         time.sleep(2)
 16         res = ‘包子%s‘ % i
 17         q.put(res)
 18         print(‘\033[44m%s制造了%s\033[0m‘ % (os.getpid(), res))
 19     q.join() #不用put(None) 了,在等q被取完。(如果数据没有被取完,生产者就不会结束掉)
 20 def product_gutou(q):
 21     for i in range(5):
 22         time.sleep(2)
 23         res = ‘骨头%s‘ % i
 24         q.put(res)
 25         print(‘\033[44m%s制造了%s\033[0m‘ % (os.getpid(), res))
 26     q.join()
 27 def product_doujiang(q):
 28     for i in range(5):
 29         time.sleep(2)
 30         res = ‘豆浆%s‘ % i
 31         q.put(res)
 32         print(‘\033[44m%s制造了%s\033[0m‘ % (os.getpid(), res))
 33     q.join()
 34
 35 if __name__ == ‘__main__‘:
 36     q = JoinableQueue()
 37     # 生产者们:厨师们
 38     p1 = Process(target=product_baozi,args=(q,))
 39     p2 = Process(target=product_doujiang,args=(q,))
 40     p3 = Process(target=product_gutou,args=(q,))
 41
 42     #消费者们:吃货们
 43     p4 = Process(target=consumer,args=(q,))
 44     p5 = Process(target=consumer,args=(q,))
 45     p4.daemon = True
 46     p5.daemon = True
 47     # p1.start()
 48     # p2.start()
 49     # p3.start()
 50     # p4.start()
 51     # p5.start()
 52     li = [p1,p2,p3,p4,p5]
 53     for i in li:
 54         i.start()
 55     p1.join()
 56     p2.join()
 57     p3.join()
 58     print(‘主‘)
 59
 60 

多生产者与多消费2

  方式二:管道(不推荐使用,了解即可)

管道相当于队列,但是管道不自动加锁

  方式三:共享数据(不推荐使用,了解即可)

共享数据也没有自动加锁的功能,所以还是推荐用队列的。感兴趣的可以研究研究管道和共享数据

归类: 网络编程socket

原文地址:https://www.cnblogs.com/lz1996/p/11575115.html

时间: 2024-11-05 23:37:07

python并发编程之多进程1------互斥锁与进程间的通信的相关文章

python并发编程之多进程

python并发编程之多进程 一.什么是进程 进程:正在进行的一个过程或者一个任务,执行任务的是CPU. 原理:单核加多道技术 二.进程与程序的区别 进程是指程序的运行过程 需要强调的是:同一个程序执行两次是两个进程,比如打开暴风影音,虽然都是同一个软件,但是一个可以播放苍井空,另一个可以播放武藤兰. 三.并发与并行 无论是并行还是并发,在用户看来都是'同时'运行的,不管是进程还是线程,都只是一个任务而已,真是干活的是cpu,cpu来做这些任务,而一个cpu同一时刻只能执行一个任务. (1)并发

进程,操作系统,Python并发编程之多进程

1.进程基础知识 1.程序:若干文件 2.进程:一个正在执行的文件,程序 3.进程被谁执行:cpu最终运行指定的程序 4.操作系统调度作用:将磁盘上的程序加载到内存,然后交由CPU去处理,一个CPU正在运行的一个程序,就叫开启了一个进程 2.操作系统 1.操作系统:存在于硬盘与软件之间,管理.协调.控制软件与硬件的交互 2.操作系统的作用:将一些复杂的硬件封装成简单的借口,便于使用;合理地调度分配多个进程与cpu的关系,让其有序化 3.操作系统发展史 ①第一代电子计算机(1940-1955) 二

python并发编程02/多进程

目录 python并发编程02/多进程 1.进程创建的两种方式 1.1开启进程的第一种方式 1.2开启进程的第二种方式 1.3简单应用 2.进程pid 2.1命令行获取所有的进程的pid tasklist 2.2代码级别如何获取一个进程的pid 2.3获取父进程(主进程)的pid 3.验证进程之间的空间隔离 4.进程对象join方法 5.进程对象其他属性 6.守护进程 python并发编程02/多进程 1.进程创建的两种方式 1.1开启进程的第一种方式 from multiProcessing

python-学习-python并发编程之多进程与多线程

一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程.Python提供了multiprocessing.    multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模块threading的编程接口类似.  multiprocessing模块的功能众多:支持子进程.通信和共享数据.执行不同形式的同步,

python并发编程之多进程(二):互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型

一,互斥锁,同步锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进程共享同一打印终端 #并发运行,效率高,但竞争同一打印终端,带来了打印错乱 from multiprocessing import Process import os,time def work(): print('%s is running' %os.getpid()) time.sleep(2) print('

二 python并发编程之多进程-重点

一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程.Python提供了multiprocessing.    multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模块threading的编程接口类似.  multiprocessing模块的功能众多:支持子进程.通信和共享数据.执行不同形式的同步,

python 并发编程 多线程 GIL全局解释器锁基本概念

首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念. 就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码. >有名的编译器例如GCC,INTEL C++,Visual C++等.Python也一样,同样一段代码可以通过CPython,PyPy,Psyco等不同的Python执行环境来执行. 像其中的JPython就没有GIL.然而因为CPython是大部分环境下默认的Python执行环境.所以在很多人的概

二 python并发编程之多进程-理论

一 什么是进程 进程:正在进行的一个过程或者说一个任务.而负责执行任务则是cpu. 举例(单核+多道,实现多个进程的并发执行): egon在一个时间段内有很多任务要做:python备课的任务,写书的任务,交女朋友的任务,王者荣耀上分的任务, 但egon同一时刻只能做一个任务(cpu同一时间只能干一个活),如何才能玩出多个任务并发执行的效果? egon备一会课,再去跟李杰的女朋友聊聊天,再去打一会王者荣耀....这就保证了每个任务都在进行中. 二 进程与程序的区别 程序仅仅只是一堆代码而已,而进程

python并发编程之多进程(实现)

一.multipricessing模块的介绍 python中的多线程无法利用多核优势,如果想要充分的使用多核CPU资源,在python中大部分情况下需要用多线程,python提供了multiprocessing模块 multiprocessing模块用来开启子进程,并在子进程中执行我们的任务(比如函数),该模块与多线程模块threading类的编程接口类似. multiprocessing模块的功能众多:支持子进程.通信和共享数据,执行不同形式的同步,提供了Process类,Queue类,Pip