2017/11/4 进程间通信,进程池
进程间通信(IPC,inter-process communication):生产进程生产食物,消费进程购买食物,消费进程一直监视生产状况,只要一有食物就将其取出来,如果取到食物None,两者关系结束,于是主进程也结束。
远程过程调用协议(remote procedure call protocal),需要某些传输协议
一般情况下 父进程会等子进程结束再结束
=====================================================================
1.进程间通信常用方式:
进程间传递数据
(1)队列:
from multiprocessing import Queue(multiprocessing.Queue)
(前一章:from queue import PriorityQueue
A.from multiprocessing import Queue(multiprocessing.Queue):
在多线程中传递数据,交换数据,进行通信;
它与一般的数据结构中的队列的差别为更加符合多进程的特性:序列化和反序列化;
对数据做了一些通信商的加工,保证多进程的安全性;
在这里使用多进程的数据通信,不需要考虑多进程可能带来的安全隐患,直接使用;
multiprocessing.Queue在进程间通信是python比价提倡的一种方式
B.from queue import PriorityQueue(queue.PriorityQueue):
存储数据的一种数据结构
(2)管道:
管道中,子进程间只能单向通信,一个子进程在定义管道后只能get或者put;
conn1只能接消息,conn2只能发送消息,不用的一端close(原因在于单缓存),如果要实现双向通信,就设置两根管道
但是队列中子进程既可以get也可以put;
匿名管道:只能在父子进程中使用
命名管道:没有沁园关系的进程之间也可以通信
(3)文件:
open,read,write,seek,tell,close
mode:r,w,a,b
with open('test.txt') as f: #该操作方式可以自行关闭文件 不必f.close()
早期时各种硬件设备都是私有接口,unix系统将设备文件化,用r,w,a,b等api接口对设备进行操作
(4)共享内存
-------------------------------
进程间传递信号
(5)信号量
(6)事件
(7)互斥量
from multiprocessing import Lock
lock.acquire()
money.value += 1 #注意锁的粒度,尽快最小话,开销最小;粒度最小原则
lock.release()
--------------------------------
(8)Socket
=====================================================================
作业:
(1)队列实现生产者消费者模型;生产者生产[0,1,2,3,4,5,6,7,8,9,10]
消费者能够在处理完list序列后退出
(2)使用互斥锁去完成银行存取款操作,存款10000,A取10次,每次取100;B存5次,每次存200
(3)面向对象方法实现第一个作业的第二题myTimer
(1)
from multiprocessing import Queue
from multiprocessing import Process
import time
def consumer(input_q):
while True:
item = input_q.get()
if item == None:
break
print(item)
def producer(sequence,output_p):
for i in sequence:
time.sleep(1)
output_p.put(i)
if __name__ == '__main__':
q= Queue()
con_p = Process(target=consumer,args=(q,))
con_p.start()
sequence =[1,2,3,4,5,6,7,8,9,10]
producer(sequence,q)
q.put(None)
(2)
from multiprocessing import Process
from multiprocessing import Value #在不同的进程间共享的变量
from multiprocessing import Lock
import time
def deposit(money,lock): #存钱
for i in range(5):
time.sleep(0.001)
lock.acquire() #上锁的操作
money.value += 200
lock.release()
def withdraw(money,lock): #取钱
for i in range(10):
time.sleep(0.001)
lock.acquire()
money.value -= 100
lock.release()
if __name__ == '__main__':
money = Value('i',2000)
lock = Lock()
d = Process(target=deposit,args=(money,lock))
d.start()
w = Process(target=withdraw,args=(money,lock))
w.start()
d.join()
w.join()
print(money.value)
(3)
from multiprocessing import Process
import time
import os
class Proces:
def __init__(set,interval):
self.interval = interval
def new_start(self):
p = Process(target = self.run,args =())
p.start()
print('child process id is %d,name is %s' % (p.pid,p.name))
print(os.getpriority(os.PRIO_PROCESS,p.pid))
os.setpriority(os.PRIO_PROCESS,p.pid,1) #获取进程改优先级
print(os.getpriority(os.PRIO_PROCESS,p.pid))
p.join()
print('main process')
class Timer(Proces):
def __init__(self,interval):
self.interval = interval
def run(self): #打印时间的方法
for i in range(5):
time.sleep(self.interval)
print(time.ctime()+'have a rest')
if __name__ == '__main__':
t = Timer(2) #创建定时器
t.new_start() #继承process do not call run 父类中函数会自动调用这个run方法
================================================================================================
相关代码:
设置优先级1-20,做一个模拟os的调度程序:某一时刻,四个进程:
Watch TV: random优先级 import rnadom
Listen to music: random优先级
Print Doc: 4
Write Doc: 4
创建队列,信息放进队列,模拟队列的调度(观察取数情况,验证时间片)
我的解法:
from queue import PriorityQueue
# import random
# class Item(object):
# def __init__(self,name,level): #self 可以将属性写进去
# self.name = name
# self.level = level
# def __repr__(self):
# return (str(self.name) + ':' + str(self.level))
# def __lt__(self,other): #小于的比较 重写
# return self.level > other.level
# if __name__ == '__main__':
# q = PriorityQueue()
# q.put(Item('watch tv',random.randint(1,20)))
# q.put(Item('music',random.randint(1,20)))
# q.put(Item('print',4))
# q.put(Item('write',4))
# while not q.empty():
# print(q.get())
#===============================================================================================
多进程定期器:每一个小时,你的定时器提示你:不要coding,休息一下吧!
提示的同时显示当前进程的pid,name,os模块设置优先级
我的解法:
# from multiprocessing import Process
# import time
# def getTime(interval):
# while True:
# time.sleep(interval)
# print(time.ctime())
# if __name__ == '__main__':
# p = Process(target=getTime,args=(1,))
# p.start()
# print(p.name,p.pid) #子进程 子进程的id
# p.join() #等待子进程结束 实际是阻塞
# print('ending') #由于子进程无线循环,由于join(),导致主进程无法运行,等待子进程结束,形成阻塞
#===============================================================================================
#显示进程id,优先级
# from multiprocessing import Process
# import time
# import os
# def getTime(interval):
# while True:
# time.sleep(interval)
# print(time.ctime())
# if __name__ == '__main__':
# p = Process(target=getTime,args=(1,))
# p.start()
# print('子进程的名字和id:',p.name,p.pid) #子进程 子进程的id
# print(os.getpriority(os.PRIO_PROCESS,p.pid))
# os.setpriority(os.PRIO_PROCESS,p.pid,1) #获取进程改优先级
# print(os.getpriority(os.PRIO_PROCESS,p.pid))
# p.join() #等待子进程结束 实际是阻塞
# print('ending') #由于子进程无线循环,由于join(),导致主进程无法运行,等待子进程结束,形成阻塞
#===============================================================================================
#将定时器改成面向对象的形式@@@@@@@@@@@@@已经完成,在20171106代码文件中
# from multiprocessing import Process
# import time
# import os
# class Timer(Process):
# def __init__(self,interval):
# self.sleep = interval
# def run(self): #打印时间的方法
time.sleep(interval)
print(time.ctime()+'have a rest')
print(os.getpriority(os.PRIO_PROCESS,p.pid))
os.setpriority(os.PRIO_PROCESS,p.pid,1) #获取进程改优先级
print(os.getpriority(os.PRIO_PROCESS,p.pid))
# if __name__ == '__main__':
# t = Timer(3600) #创建定时器
# t.start() #继承process do not call run 父类中函数会自动调用这个run方法
#===============================================================================================
#===============================================================================================
20171104作业 - 老师的解法
设置优先级1-20,做一个模拟os的调度程序:某一时刻,四个进程:
Watch TV: random优先级 import rnadom
Listen to music: random优先级
Print Doc: 4
Write Doc: 4
创建队列,信息放进队列,模拟队列的调度(观察取数情况,验证时间片)
# from queue import PriorityQueue
# import random
# class Item(object):
# def __init__(self,name,level): #self 可以将属性写进去
# self.name = name
# self.level = level
# def __repr__(self):
# return (str(self.name) + ':' + str(self.level))
# def __lt__(self,other): #小于的比较 重写
# return self.level > other.level
# if __name__ == '__main__':
# q = PriorityQueue()
# q.put(Item('watch tv',random.randint(1,20)))
# q.put(Item('music',random.randint(1,20)))
# q.put(Item('print',4))
# q.put(Item('write',4))
# while not q.empty():
# print(q.get())
# q.put(Item('print',4+q.qsize()))
# q.put(Item('write',4+q.qsize()))
#===============================================================================================
20171104作业- 老师的解法
多进程定期器:每一个小时,你的定时器提示你:不要coding,休息一下吧!
提示的同时显示当前进程的pid,name,os模块设置优先级
# from multiprocessing import Process
# import time
# def getTime(interval):
# while True:
# time.sleep(interval)
# print(time.ctime())
# if __name__ == '__main__':
# p = Process(target=getTime,args=(1,))
# p.start()
# print(p.name,p.pid) #子进程 子进程的id
# p.join() #等待子进程结束 实际是阻塞
# print('ending') #由于子进程无线循环,由于join(),导致主进程无法运行,等待子进程结束,形成阻塞
#==================================
#显示进程id,优先级
# from multiprocessing import Process
# import time
# import os
# def getTime(interval):
# while True:
# time.sleep(interval)
# print(time.ctime())
# if __name__ == '__main__':
# p = Process(target=getTime,args=(1,))
# p.start()
# print('子进程的名字和id:',p.name,p.pid) #子进程 子进程的id
# print(os.getpriority(os.PRIO_PROCESS,p.pid))
# os.setpriority(os.PRIO_PROCESS,p.pid,1) #获取进程改优先级
# print(os.getpriority(os.PRIO_PROCESS,p.pid))
# p.join() #等待子进程结束 实际是阻塞
# print('ending') #由于子进程无线循环,由于join(),导致主进程无法运行,等待子进程结束,形成阻塞
#=================================
#将定时器改成面向对象的形式
# from multiprocessing import Process
# import time
# import os
# class Timer(Process):
# def __init__(self,interval):
# self.sleep = interval
# def run(self): #打印时间的方法
# time.sleep(interval)
# print(time.ctime()+'have a rest')
# print(os.getpriority(os.PRIO_PROCESS,p.pid))
# os.setpriority(os.PRIO_PROCESS,p.pid,1) #获取进程改优先级
# print(os.getpriority(os.PRIO_PROCESS,p.pid))
# if __name__ == '__main__':
# t = Timer(3600) #创建定时器
# t.start() #继承process do not call run 父类中函数会自动调用这个run方法
#===============================================================================================
#===============================================================================================
20171106课堂练习代码
#生产消费模型
# from multiprocessing import Queue
# from multiprocessing import Process
# import time
# #消费者模型
# def consumer(input_q):
# time.sleep(2)
# while not input_q.empty():
# print(input_q.get())
# #生产者逻辑
# def producer(sequence,output_p):
# for i in sequence:
# output_p.put(i)
# if __name__ == '__main__':
# q= Queue()
# con_p = Process(target=consumer,args=(q,))
# con_p.start()
# sequence =[1,2,3,4,5]
# producer(sequence,q)
#=================================
#生产消费模型
# from multiprocessing import Queue
# from multiprocessing import Process
# import time
# #消费者模型
# def consumer(input_q):
# time.sleep(2)
# while True:
# if not input_q.empty():
# print(input_q.get())
# else:
# break
# #生产者逻辑
# def producer(sequence,output_p):
# for i in sequence:
# output_p.put(i)
# if __name__ == '__main__':
# q= Queue()
# con_p = Process(target=consumer,args=(q,))
# con_p.start()
# sequence =[1,2,3,4,5]
# producer(sequence,q)
#=================================
# #生产消费模型
# from multiprocessing import Queue
# from multiprocessing import Process
# import time
# #消费者模型
# def consumer(input_q): #input_q 声明参数 从生产者那里拿走物品(数据,队列数据)
# while True:
# item = input_q.get()
# if item == None: #用None作为标志,判断生产者是否已经结束了生产
# break
# print(item)
# #生产者逻辑
# def producer(sequence,output_p):
# for i in sequence:
# time.sleep(1)
# output_p.put(i)
# if __name__ == '__main__':
# q= Queue()
# con_p = Process(target=consumer,args=(q,)) #消费者进程 创建一个进程,进程的目标一定是个函数名,或者值类中的函数名即方法名,进程的参数
# con_p.start()
# sequence =[1,2,3,4,5]
# # pro_p = Process(target=producer,args=(sequence,q)) #消费者进程
# # pro_p.start()
# producer(sequence,q) # 生产者开始生产数字12345,放入队列中
# q.put(None) # 向队列中放入一个空值(或者说是生产一个空值),空值也是值,是一个特殊的值
#=================================
# #生产消费模型 队列 演示一个子进程既可以put 也可以get
# from multiprocessing import Queue
# from multiprocessing import Process
# import time
# #消费者模型
# def consumer(input_q): #input_q 声明参数 从生产者那里拿走物品(数据,队列数据)
# while True:
# item = input_q.get()
# if item == None: #用None作为标志,判断生产者是否已经结束了生产
# # input_q.put(6)
# break
# print(item)
# #生产者逻辑
# def producer(sequence,output_p):
# for i in sequence:
# time.sleep(1)
# output_p.put(i)
# if __name__ == '__main__':
# q= Queue()
# con_p = Process(target=consumer,args=(q,)) #消费者进程 创建一个进程,进程的目标一定是个函数名,或者值类中的函数名即方法名,进程的参数
# con_p.start()
# sequence =[1,2,3,4,5]
# # pro_p = Process(target=producer,args=(sequence,q)) #消费者进程
# # pro_p.start()
# producer(sequence,q) # 生产者开始生产数字12345,放入队列中
# # con_p.join() #一定等子进程结束,保证consumer也能向队列中添加数字6 表明对列中子进程的双方既可以put,也可以get,而管道只能单向,一个子进程在定义管道后只能get或者put
# q.put(None) # 向队列中放入一个空值(或者说是生产一个空值),空值也是值,是一个特殊的值
#===============================================================================================
# #管道操作-仅了解
# from multiprocessing import Pipe
# from multiprocessing import Process
# #消费者模型
# def consumer(pipe):
# (conn1,conn2) = pipe #两个变量构成一个管道,管道是设置的参数pipe
# conn2.close() #关闭管道的发送方!!!
# while True:
# try:
# item = conn1.recv()
# print(item)
# except EOFError: #文件读取错误
# break
# print('consumer ending done')
# #生产者逻辑
# def producer(sequence,sendPipe):
# for i in sequence:
# sendPipe.send(i)
# if __name__ == '__main__':
# (conn1,conn2) = Pipe() #创建管道,conn1是接收方 conn2是发送方
# con_p = Process(target=consumer,args=((conn1,conn2),)) #创建消费者子进程,把管道(元组)作为参数传入;生产者为主进程
# con_p.start()
# conn1.close() #关闭生产者的输出管道
# sequence =[1,2,3,4,5] #这里还要用到发送方
# producer(sequence,conn2)
# conn2.close()
#=================================
# #管道操作- 仅了解
# from multiprocessing import Pipe
# from multiprocessing import Process
# #消费者模型
# def consumer(pipe):
# (conn1,conn2) = pipe
# conn2.close()
# while True:
# try:
# item = conn1.recv()
# except EOFError:
# conn1.close()
# break
# print(item)
# print('consumer ending done')
# #生产者逻辑
# def producer(sequence,sendPipe):
# for i in sequence:
# sendPipe.send(i)
# if __name__ == '__main__':
# (conn1,conn2) = Pipe() #创建管道,conn1是接收方 conn2是发送方
# con_p = Process(target=consumer,args=((conn1,conn2),)) #创建消费者子进程,把管道(元组)作为参数传入;生产者为主进程
# con_p.start()
# conn1.close() #关闭生产者的输出管道
# sequence =[1,2,3,4,5] #这里还要用到发送方
# producer(sequence,conn2)
# conn2.close()
#===============================================================================================
# #银行存取款demo1 正常
# from multiprocessing import Process
# from multiprocessing import Value #在不同的进程间共享的变量
# import time
# def deposit(money): #存钱
# for i in range(100):
# money.value += 1
# def withdraw(money): #取钱
# for i in range(100):
# money.value -= 1
# if __name__ == '__main__':
# money = Value('i',2000) #共享变量 int 数值2000
# d = Process(target=deposit,args=(money,))
# d.start()
# w = Process(target=withdraw,args=(money,))
# w.start()
# d.join()
# w.join()
# print(money.value) #三个进程一起跑 不一定会执行词句 需要等待子进程结束
#=================================
# #银行存取款demo1 - 存取款异常
前提知识1:多进程不能访问同一个全局变量,原因是不同的进程使用的虚拟内存空间不同,而全局变量实际是用的同一个内存空间,
因此需要 import Value 生成一个能够在不同的进程间共享和操作的变量
前提知识2:对于time.sleep ,在一个程序中,子进程之间会抢占资源,比如抢占 value ,看a在睡醒的时刻是否能够抢占到资源value
# from multiprocessing import Process
# from multiprocessing import Value #在不同的进程间共享的变量
# import time
# def deposit(money): #存钱
# for i in range(100):
# time.sleep(0.1)
# money.value += 1
# def withdraw(money): #取钱
# for i in range(100):
# time.sleep(0.1)
# money.value -= 1
# if __name__ == '__main__':
# money = Value('i',2000) #共享变量 int 数值2000
# d = Process(target=deposit,args=(money,))
# d.start()
# w = Process(target=withdraw,args=(money,))
# w.start()
# d.join()
# w.join()
# print(money.value) #三个进程一起跑 不一定会执行词句 需要等待子进程结束
#=================================
#银行存取款demo2 - 存取款异常-解决 —— 锁1
from multiprocessing import Process
from multiprocessing import Value #在不同的进程间共享的变量
from multiprocessing import Lock
import time
def deposit(money,lock): #存钱
# lock.acquire() #上锁的操作
for i in range(100):
time.sleep(10)
money.value += 1
# lock.release()
def withdraw(money,lock): #取钱
# lock.acquire() #上锁的操作
for i in range(100):
time.sleep(0.0001)
money.value -= 1
# lock.release()
if __name__ == '__main__':
money = Value('i',2000) #共享变量 int 数值2000
lock = Lock() #银行为了安全 加了一把互斥锁
d = Process(target=deposit,args=(money,lock))
d.start()
w = Process(target=withdraw,args=(money,lock))
w.start()
d.join()
w.join()
print(money.value) #三个进程一起跑 不一定会执行词句 需要等待子进程结束
#=================================
# #银行存取款demo3 - 存取款异常-解决 —— 锁2 -更优 因为锁的力度更小,时间更短
# from multiprocessing import Process
# from multiprocessing import Value #在不同的进程间共享的变量
# from multiprocessing import Lock
# import time
# def deposit(money,lock): #存钱
# for i in range(100):
# time.sleep(0.1)
# lock.acquire() #上锁的操作
# money.value += 1
# lock.release()
# def withdraw(money,lock): #取钱
# for i in range(100):
# time.sleep(0.1)
# lock.acquire() #上锁的操作
# money.value -= 1
# lock.release()
# if __name__ == '__main__':
# money = Value('i',2000) #共享变量 int 数值2000
# lock = Lock() #银行为了安全 加了一把互斥锁
# d = Process(target=deposit,args=(money,lock))
# d.start()
# w = Process(target=withdraw,args=(money,lock))
# w.start()
# d.join()
# w.join()
# print(money.value) #三个进程一起跑 不一定会执行词句 需要等待子进程结束,因此添加join方法
python多进程之间怎么共享一个队列
转载本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。
上一篇:把iOS刻录到U盘的工具
下一篇:nginx局域网远程控制
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
fineReport的redis配置 finereport help
一、9.0版本安装 双击, 傻瓜式安装: 根据需要修改安装路径、设置FineReport软件工具最大jvm,默认为2048M, 首次登陆:注册好账号,弹出页面,点击立即获取,继续完成信息填写,获取
fineReport的redis配置 FineReport 9.0安装使用 数据集 数据 数据连接