并发编程——多进程——multiprocessing开启进程的方式及其属性(3)
- 开启进程的两种方式——Process
- 方式一:函数方法
from multiprocessing import Process
import time
def task(name):
print('%s is running'%name)
time.sleep(3)
print('%s is done' % name)
if __name__ == '__main__':
p = Process(target=task,args=('子进程1',))
p.start() #仅仅只是给操作系统发送了一个信号 print('主进程')方式一
- 方式二:类方法
from multiprocessing import Process
import time,os
class MyProcess(Process):
def __init__(self,name):
super().__init__()
self.name = name
def run(self):
print('%s is running'%self.name,os.getppid())
time.sleep(3)
print('%s is done' % self.name,os.getppid())
if __name__ == '__main__':
p = MyProcess('子进程1')
p.start() print('主进程',os.getpid())方式二
- 进程id
- 子进程id : os.getpid()
- 父进程id : os.getppid()
- 僵尸进程与孤儿进程(仅存在于linux和unix系统中)
- 僵尸进程:在Linux系统中,任何子进程都会经历僵尸进程模式,以便父进程查看子进程状态,pid不会丢失,占用pid资源,在父进程一直不死的情况下有害
- 孤儿进程:父进程已死,子进程依然活着;孤儿进程会被一个INIT进程收留,是无害的。
- Process的方法介绍
- p.start():启动进程,并调用该子进程中的p.run()
- p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法
p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁
- p.is_alive():如果进程p仍然运行,返回True
- p.join([timeout]):主进程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout 是可选的超时时间。
- p.name:查看子进程的进程名,即使子进程终止了,也可以查到
- join方法
def talk(name):
print("%s 开始说话"%name)
time.sleep(random.randint(1,5))
print("%s 说话结束" %name)
if __name__ == '__main__':
# freeze_support()
p1 = Process(target=talk,args=(1,))
p2 = Process(target=talk,args=(2,))
p3 = Process(target=talk,args=(3,))
p = [p1,p2,p3]
for i in p:
i.start()
# p1.terminate()
for i in p:
i.join() print("主进程结束")join方法
- join是主进程在等子进程结束,当有多个子进程时,子进程之间依然是并发的
- 守护进程
- 守护进程会在主进程代码执行结束后就终止,字随父死
- 守护进程内无法再开启子进程,否则抛出异常
#-*- coding:utf-8 -*-
import time
from multiprocessing import Process
def task(name):
print("子进程%s开始执行"%name)
time.sleep(2)
# p = Process(target=time.time,args=(3,))
# p.start()
print("子进程%s执行完毕"%name)
if __name__ == '__main__':
p = Process(target=task,args = (1,))
p.daemon = True
p.start()
# p.join()
print("主")守护进程
- 互斥锁
- 把并发变成串行,牺牲效率,保证数据的正确性
- 前提:共享同一套文件系统(存储于硬盘中)
- 存在的问题:效率低,需要自己加锁处理
#-*- coding:utf-8 -*-
from multiprocessing import Process,Lock
import os,time
def work(lock):
lock.acquire()#加锁
print('%s is running' %os.getpid())
time.sleep(2)
print('%s is done' %os.getpid())
lock.release()#释放锁 if __name__ == '__main__':
lock = Lock()
for i in range(3):
p=Process(target=work,args=(lock,))
p.start()互斥锁
- 与join的区别
- join是将一个任务整体串行
- 互斥锁:可以将一个任务中的某一段代码串行
# -*- coding:utf-8 -*-
import json
import time
from multiprocessing import Process,Lock def search(name):
time.sleep(1)
dic = json.load(open('db.txt','r',encoding='utf-8'))
print('<%s>查看到剩余票数[%s]' % (name, dic['count'])) def get(name,lock):
lock.acquire()
time.sleep(1)
dic = json.load(open('db.txt', 'r', encoding='utf-8'))
if dic['count'] > 0:
dic['count'] -= 1
time.sleep(3)
json.dump(dic, open('db.txt', 'w', encoding='utf-8'))
print('<%s>购票成功' % name)
lock.release() def task(name,lock):
search(name)
get(name,lock) if __name__ == '__main__':
lock = Lock() for i in range(1,10):
p = Process(target=task, args=(i,lock))
p.start()
# p.join()模拟抢票
- 队列
- 队列和管道都是将数据存放于内存中,而队列又是基于(管道+锁)实现的,可以让我们从复杂的锁问题中解脱出来,因而队列才是进程间通信(IPC)的最佳选择
- 创建队列的类:Queue([maxsize])
- [maxsize]是队列中允许最大项数,省略则无大小限制
- 队列内存放的是消息而非大数据
- 队列占用的是内存空间,因而maxsize即便是无大小限制也受限于内存大小
#-*- coding:utf-8 -*-
from multiprocessing import Process,Queue
q = Queue(3)
q.put(1)
q.put(2)
q.put(3)
print(q.full())
# q.put(4)#再放就阻塞了 print(q.get())
print(q.get())
print(q.get())
print(q.empty())#空了
# print(q.get())#再取就阻塞了队列
- 生产者消费者模型
- 什么是生产者消费者模型
- 生产者消费者模型是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列中取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
- 什么是生产者消费者模型
- 程序中有两类角色
- 一类负责生产数据(生产者)
- 一类负责处理数据(消费者)
- 引入生产者消费者模型是为了解决的问题是
- 平衡生产者与消费者之间的速度差
- 程序解开耦合
- 如何实现生产者消费者模型
- 生产者<--->队列<--->消费者
#-*- coding:utf-8 -*-
from multiprocessing import Process,Queue
import time
import random
import os
def consumer(q,name):
while True:
res = q.get()
if res is None:break
time.sleep(random.randint(1,3))
print('\033[43m%s 吃 %s\033[0m' %(name,res))
def producer(q,name,food):
for i in range(3):
time.sleep(random.randint(1,3))
res = '%s%s'%(food,i)
q.put(res)
print('\033[45m%s 生产了 %s\033[0m' % (name, res))
if __name__ == '__main__':
q = Queue()
#生产者们,即厨师
p1 = Process(target=producer,args=(q,'egon1','包子'))
p2 = Process(target=producer,args=(q,'egon2','骨头'))
p3 = Process(target=producer,args=(q,'egon3','饺子')) #消费者们:即吃货们
c1 = Process(target=consumer,args=(q,'alex1'))
c2 = Process(target=consumer,args=(q,'alex2')) #开始
p1.start()
p2.start()
p3.start()
c1.start()
c2.start()
p1.join()
p2.join()
p3.join()
q.put(None)
q.put(None)
q.put(None)
print('主程序结束')生产者消费者模型
- 程序中有两类角色
- JoinableQueue([maxsize])
- JoinableQueue的实例p除了与Queue对象相同的方法之外还具有:
- q.task_done():使用者使用此方法发出信号,表示q.get()的返回项目已经被处理。如果调用此方法的次数大于从队列中删除项目的数量,将引发ValueError异常
- q.join():生产者调用此方法进行阻塞,知道队列中所有的项目均被处理。阻塞将持续到队列中的每个项目均调用q.task_done()方法为止。
#-*- coding:utf-8 -*-
from multiprocessing import Process,JoinableQueue
import time,random,os
def consumer(q,name):
while True:
res = q.get()
time.sleep(random.randint(1,3))
print('\033[43m%s 吃 %s\033[0m' %(name,res))
q.task_done()#发送信号给q.join(),说明已经从队列中取走一个数据并处理完毕了
def producer(q,name,food):
for i in range(3):
time.sleep(random.randint(1,3))
res = '%s%s'%(food,i)
q.put(res)
print('\033[45m%s 生产了 %s\033[0m' % (name, res))
q.join()#等到消费者把自己放入队列中的所有的数据都取走之后,生产者才结束 if __name__ == "__main__":
q = JoinableQueue()#使用JoinableQueue()
#生产者们:即厨师们
p1 = Process(target=producer, args=(q, 'egon1', '包子'))
p2 = Process(target=producer, args=(q, 'egon2', '骨头'))
p3 = Process(target=producer, args=(q, 'egon3', '泔水'))
# 消费者们:即吃货们
c1 = Process(target=consumer, args=(q, 'alex1'))
c2 = Process(target=consumer, args=(q, 'alex2'))
c1.daemon = True
c2.daemon = True
# 开始
p1.start()
p2.start()
p3.start()
c1.start()
c2.start()
p1.join()
p2.join()
p3.join()
#1、主进程等生产者p1、p2、p3结束
#2、而p1、p2、p3是在消费者把所有数据都取干净之后才会结束
#3、所以一旦p1、p2、p3结束了,证明消费者也没必要存在了,应该随着主进程一块死掉,因而需要将生产者们设置成守护进程
print('主')使用JoinableQueue实现消费者生产者模型
并发编程——多进程——multiprocessing开启进程的方式及其属性(3)的更多相关文章
- Python 3 并发编程多进程之守护进程
Python 3 并发编程多进程之守护进程 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemo ...
- python_并发编程——多进程的第二种启动方式
1.多进程的第二种启动方式 import os from multiprocessing import Process # 创建一个自定义类,继承Process类 class MyProcess(Pr ...
- python网络编程之开启进程的方式
标签(空格分隔): 开启进程的方式 multiprocessing模块介绍: python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在pyth ...
- python并发编程基础之守护进程、队列、锁
并发编程2 1.守护进程 什么是守护进程? 表示进程A守护进程B,当被守护进程B结束后,进程A也就结束. from multiprocessing import Process import time ...
- Cpython解释器下实现并发编程——多进程、多线程、协程、IO模型
一.背景知识 进程即正在执行的一个过程.进程是对正在运行的程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其他所有内容都 ...
- python并发编程&多进程(二)
前导理论知识见:python并发编程&多进程(一) 一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_cou ...
- python并发编程&多进程(一)
本篇理论居多,实际操作见: python并发编程&多进程(二) 一 什么是进程 进程:正在进行的一个过程或者说一个任务.而负责执行任务则是cpu. 举例(单核+多道,实现多个进程的并发执行) ...
- Python 3 并发编程多进程之队列(推荐使用)
Python 3 并发编程多进程之队列(推荐使用) 进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的. 可以往 ...
- python 并发编程 多进程 目录
python multiprocessing模块 介绍 python 开启进程两种方法 python 并发编程 查看进程的id pid与父进程id ppid python 并发编程 多进程 Proce ...
随机推荐
- uvm_tlm_if_base——TLM1事务级建模方法(三)
文件: src/tlm1/uvm_tlm_ifs.svh 类: uvm_tlm_if_base 这个类没有派生自任何类,在类的中,定义了三类接口:第一类是阻塞性质的普通方法(task),put, ge ...
- MVC下c#对接微信公众平台开发者模式
在ashx文件中进行HttpContext的处理: using System; using System.Collections.Generic; using System.Linq; using S ...
- [转]超全!iOS 面试题汇总
转自:http://www.cocoachina.com/programmer/20151019/13746.html 1. Object-c的类可以多重继承么?可以实现多个接口么?Category是 ...
- python_23_tuple
#元组只能统计和获取下表,不能插入之类的.元组和列表差不多,也是存一组数,只是它一旦创建,便不能再修改,所以又叫只读列表 names=('QiZhiguang','LiuGuannan','Liang ...
- python内置函数map/reduce/filter
python有几个内置的函数很有意 思:map/filter/reduce,都是对一个集合进行处理,filter很容易理解用于过滤,map用于映射,reduce用于归并. 是python列表方法的三架 ...
- react的redux中间件
redux 的中间件(对dispatch功能的拦截和增强,一般不用自己写,有插件) dispath是一个方法,可以自行中间拦截更改: store.dispatch = function(action) ...
- 项目实战15.1—企业级堡垒机 jumpserver一步一步搭建
本文收录在Linux运维企业架构实战系列 环境准备 系统:CentOS 7 IP:192.168.10.101 关闭selinux 和防火墙 # CentOS 7 $ setenforce 0 # 可 ...
- Java泛型和反射
1. 字节码对象的三种获取方式 以String为例 Class<? extends String> strCls = "".getClass(); Class<S ...
- eclipse中使用git上传项目
eclipse中使用git上传项目 先需要上传到本地仓库 先找到此选项打钩 再如下 再添加的属性则可以自动填充邮箱和密码 之后 右键选择import 点击找到git 选中 下一步 如果没有找到git ...
- 【解决】ERROR in xxx.js from UglifyJs
当我们运行打包脚本npm run build或者打包iosweexpack build ios有可能会遇到以下报错 ERROR in index.js from UglifyJs ![](https: ...