进程与进程之间是相互独立的,互不干扰。如果多进程之间需要对同一资源操作,就需要进程间共享变量,上一篇文章介绍了进程间共享数据的三大类Value、Array、Manager,这三种类的主要区别在于管理的数据类型不同。解决了进程间共享数据的问题,又有新的问题产生,那就是当多进程同时对一个共享资源进行写操作时,容易造成数据混乱。如何解决这一问题呢?这就需要进程间相互协同。
进程间相互协同的方式有如下几种:
Lock:加锁,accquire()申请锁,release()释放锁
Queue:队列
Semaphore:信号量
Event:事件
Pipe:管道
下面一一介绍这几种方式。
Lock:进程申请锁后,会阻塞其他进程获取lock对象,不能操作数据,只有锁释放后,其他进程可以重新获取锁对象。
实例代码:

from multiprocessing import Process,Value,Lock
def func1(num,lock):#传入的lock对象
lock.acquire()#申请锁,lock对象变为locked,并且阻塞其他进程获取lock对象
print num.value
num.value+=1
lock.release()#释放锁,lock对象变为unlocked,其他进程可以重新获取lock对象
if __name__ == '__main__':
lock=Lock()#创建锁对象
val=Value('i',0)
proc=[Process(target=func1,args=(val,lock)) for i in xrange(100)]
for p in proc:
p.start()
for p in proc:
p.join()

print val.value
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
运行结果:

50
1
Semaphore:信号量,同时允许多个进程申请锁
实例代码:

import multiprocessing
import time
from multiprocessing import Process,Semaphore
def func1(s):
s.acquire()
print multiprocessing.current_process().name+'acquire'
time.sleep(10)
s.release()
print multiprocessing.current_process().name+'release'
if __name__ == '__main__':
s=Semaphore(4)
procs=[Process(target=func1,args=(s,))for i in xrange(10)]
for p in procs:
p.start()
for p in procs:
p.join()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Queue:队列:多用来在多个进程间通信
实例代码:
循环等待,避免执行结果不准*

import multiprocessing
import time
def write(q):
for value in ['A','B','C']:
print 'put %s to queue '%value
q.put(value)
time.sleep(2)
def read(q):
def isEmpty():
i=0
while i<5:
if not q.empty():
return False#如果队列不等于空,退出循环不用等待
time.sleep(2)#如果列表是空,循环等待
i+=1
return True
while not isEmpty():#q.empty():
print 'get %s from queue '%q.get()
if __name__ == '__main__':
q=multiprocessing.Queue()
pw=multiprocessing.Process(target=write,args=(q,))
pr=multiprocessing.Process(target=read,args=(q,))
pw.start()
pr.start()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
运行结果:

put A to queue
get A from queue
put B to queue
get B from queue
put C to queue
get C from queue
1
2
3
4
5
6
不用循环等待的效果执行结果:

put A to queue
get A from queue
put B to queue
put C to queue
1
2
3
4
5
Event:处理某个进程的逻辑,依赖于某个事件的发生。比如到下课时间响铃,那么这个事件就可以设置成时间,来监听到没到下课时间,如果到,代码分支就是放一段音乐。

set()设置事件,wait([time]) clear()清除事件
实例代码:

import multiprocessing
import time
def waitForEvent(e):
print 'wait for event starting.No timeout'
e.wait()
print 'the event has happened.',e.is_set()
def waitForEventTimeout(e,t):
print 'wait for event starting.timeout is ',t
e.wait(t)
print 'the event has happened.',e.is_set()
if __name__ == '__main__':
e=multiprocessing.Event()
print 'the event is_set is:',e.is_set()
p=multiprocessing.Process(target=waitForEventTimeout,args=(e,2))#改成5,True
# p1=multiprocessing.Process(target=waitForEvent,args=(e,))
p.start()
# p1.start()
time.sleep(3)
e.set()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
运行结果:

the event is_set is: False
wait for event starting.timeout is 2
the event has happened. False
1
2
3
4
Pipe:管道。用来在两个进程间进行通信。
返回两个连接对象(conn1,conn2),代表管道的两端。
send() recv()
实例代码:

from multiprocessing import Process,Pipe
def func1(pipe):
pipe.send('hello')
print 'func1 received: %s'%pipe.recv()#recv是阻塞式的,等待接收消息
pipe.send('who are you?')
print 'func1 received: %s'%pipe.recv()
def func2(pipe):
print 'func2 received: %s'%pipe.recv()
pipe.send('hello too')
print 'func2 received: %s'%pipe.recv()
pipe.send("I don't tell you")
if __name__ == '__main__':
pipe=Pipe()
print len(pipe)
p1=Process(target=func1,args=(pipe[0],))
p2=Process(target=func2,args=(pipe[1],))
p1.start()
p2.start()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
执行结果:

2
func2 received: hello
func1 received: hello too
func2 received: who are you?
func1 received: I don't tell you
1
2
3
4
5
循环发送:A发一次,B回复一次收到
实例代码:

from multiprocessing import Process,Pipe
import time
def func1(pipe):
for i in xrange(10):
pipe.send('send message to func2:%s'%str(i))
recvMesg= pipe.recv()
print recvMesg
# with open('D:\\python\\pipeTestFun1.txt','w')as fp:
# fp.write(recvMesg)
def func2(pipe):
for i in xrange(10):
recvMesg=pipe.recv()
# with open('D:\\python\\pipeTestFun2.txt','w') as fp:
# fp.write(recvMesg+'\n')
sendMesg=recvMesg+' is writen to filePath'
print recvMesg
pipe.send(sendMesg)
if __name__ == '__main__':
pipe=Pipe()
p1=Process(target=func1,args=(pipe[0],))
p2=Process(target=func2,args=(pipe[1],))
p2.start()
time.sleep(1)
p1.start()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
执行结果:

send message to func2:0
send message to func2:0 is writen to filePath
send message to func2:1
send message to func2:1 is writen to filePath
send message to func2:2
send message to func2:2 is writen to filePath
send message to func2:3
send message to func2:3 is writen to filePath
send message to func2:4
send message to func2:4 is writen to filePath
---------------------
作者:Loadinggggg
来源:CSDN
原文:https://blog.csdn.net/lechunluo3/article/details/79047128
版权声明:本文为博主原创文章,转载请附上博文链接!

Python多进程编程-进程间协作(Queue、Lock、Semaphore、Event、Pipe)的更多相关文章

  1. python网络编程-进程间数据通信(Queue,Pipe ,managers)

    一:进程间数据交换方法 不同进程间内存是不共享的,要想实现两个进程间的数据交换,可以用以下方法: Queue,Pipe ,managers 1)Queue,使用方法跟threading里的queue差 ...

  2. Python并发编程-进程间数据共享

    Manager中进程数据不安全 通过加锁解决 from multiprocessing import Manager,Process,Lock def main(dic,lock): lock.acq ...

  3. Python 多进程编程之 进程间的通信(在Pool中Queue)

    Python 多进程编程之 进程间的通信(在Pool中Queue) 1,在进程池中进程间的通信,原理与普通进程之间一样,只是引用的方法不同,python对进程池通信有专用的方法 在Manager()中 ...

  4. Python 多进程编程之 进程间的通信(Queue)

    Python 多进程编程之 进程间的通信(Queue) 1,进程间通信Process有时是需要通信的,操作系统提供了很多机制来实现进程之间的通信,而Queue就是其中的一个方法----这是操作系统开辟 ...

  5. Python多进程编程

    转自:Python多进程编程 阅读目录 1. Process 2. Lock 3. Semaphore 4. Event 5. Queue 6. Pipe 7. Pool 序. multiproces ...

  6. 【转】Python多进程编程

    [转]Python多进程编程 序. multiprocessingpython中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程.Pytho ...

  7. 深入理解python多进程编程

    1.python多进程编程背景 python中的多进程最大的好处就是充分利用多核cpu的资源,不像python中的多线程,受制于GIL的限制,从而只能进行cpu分配,在python的多进程中,适合于所 ...

  8. python类库32[多进程同步Lock+Semaphore+Event]

    python类库32[多进程同步Lock+Semaphore+Event]   同步的方法基本与多线程相同. 1) Lock 当多个进程需要访问共享资源的时候,Lock可以用来避免访问的冲突. imp ...

  9. Python并发编程-进程 线程 同步锁 线程死锁和递归锁

    进程是最小的资源单位,线程是最小的执行单位 一.进程 进程:就是一个程序在一个数据集上的一次动态执行过程. 进程由三部分组成: 1.程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成 2.数据 ...

随机推荐

  1. LeetCode #807. Max Increase to Keep City Skyline 保持城市天际线

    https://leetcode-cn.com/problems/max-increase-to-keep-city-skyline/ 执行用时 : 3 ms, 在Max Increase to Ke ...

  2. BZOJ 5450 轰炸 (强连通缩点+DAG最长路)

    <题目链接> 题目大意: 有n座城市,城市之间建立了m条有向的地下通道.你需要发起若干轮轰炸,每轮可以轰炸任意多个城市.但每次轰炸的城市中,不能存在两个不同的城市i,j满足可以通过地道从城 ...

  3. bzoj2176 Strange string(字符串最小表示法)

    Time Limit: 10 Sec  Memory Limit: 259 MB 给定一个字符串S = {S1, S2, S3 … Sn}, 如果在串SS中, 子串T(|T| = n)为所有长度为n的 ...

  4. 38.0到n-1中缺失的数字

    题目描述:   一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字的范围都在0到n-1之内.在范围0到n-1内的n个数字中有且仅有一个数字不在该数组中,求出该数字. 思路分析:   因 ...

  5. Vue打包后访问静态资源路径问题

    Vue介绍中static文件夹里放的是静态资源目录,如图片.字体等. 我们发现运行npm run start后本地图片路径是没问题的,但是打包上传后会怎么样呢? 我们知道,执行npm run buil ...

  6. gitlab私钥配置

    一.Linux版 1).首先打开linux服务器,输入命令:ls -al ~/.ssh,检查是否显示有id_rsa.pub或者id_dsa.pub存在,如果存在请直接跳至第3步. 2).在bash中输 ...

  7. https://geewu.gitbooks.io/rabbitmq-quick/content/RabbitMQ%E5%9F%BA%E7%A1%80%E6%93%8D%E4%BD%9C.html

    https://geewu.gitbooks.io/rabbitmq-quick/content/RabbitMQ%E5%9F%BA%E7%A1%80%E6%93%8D%E4%BD%9C.html

  8. Hibernate性能提升

    1.大数据量批量插入造成Exception in thread "main" java.lang.OutOfMemoryError 内存溢出异常 正常插入: session.sav ...

  9. web安全—tomcat禁用WebDAV或者禁止不需要的 HTTP 方法

    现在主流的WEB服务器一般都支持WebDAV,使用WebDAV的方便性,呵呵,就不用多说了吧,用过VS.NET开发ASP.Net应用的朋友就应该 知道,新建/修改WEB项目,其实就是通过WebDAV+ ...

  10. Strcpy,strcpy使用注意

    一.char *strcpy(char *dest, const char *src) 参数 dest -- 指向用于存储复制内容的目标数组. src -- 要复制的字符串. 注意: 1.dest需要 ...