在这里,我发现了以下使用多处理模块信号量的例子(这是修改后的版本):
#!/bin/env python
import multiprocessing
from time import sleep
import os
max_allowed_processes_in_critical_section=1
semaphore = multiprocessing.Semaphore(max_allowed_processes_in_critical_section)
def do_job(id):
# BEGINNING OF CRITICAL SECTION
with semaphore:
sleep(1)
print "#####################"
print "Inside locked semaphore"
print "PPID: %s" % os.getppid()
print "PID: %s" % os.getpid()
# END OF CRITICAL SECTION
print("Finished job")
def main():
pool = multiprocessing.Pool(6)
for job_id in range(6):
print("Starting job")
pool.apply_async(do_job, [job_id])
pool.close()
pool.join()
if __name__ == "__main__":
main()
可以看到,在这个上下文中,信号量与with
关键字一起使用。一般来说,信号量有wait()
和signal()
两种方法。在python的threading
和multiprocessing
模块中,这些方法完全等同于acquire()
和release()
。我已经将代码重写为这个,它使用acquire()
和release()
方法:
#!/bin/env python
import multiprocessing
from time import sleep
import os
max_allowed_processes_in_critical_section=1
semaphore = multiprocessing.Semaphore(max_allowed_processes_in_critical_section)
def do_job(id):
# BEGINNING OF CRITICAL SECTION
semaphore.acquire()
sleep(1)
print "#####################"
print "Inside locked semaphore"
print "PPID: %s" % os.getppid()
print "PID: %s" % os.getpid()
semaphore.release()
# END OF CRITICAL SECTION
print("Finished job")
def main():
pool = multiprocessing.Pool(6)
for job_id in range(6):
print("Starting job")
pool.apply_async(do_job, [job_id])
pool.close()
pool.join()
if __name__ == "__main__":
main()
从我之前的问题中,我了解到,当某些方法与with
关键字一起使用时,上下文管理器的__enter__()
和__exit__()
方法在从with
语句的主体进入(和分别退出)时被调用。所以我假设acquire()
在__enter__()
中被调用,release()
在__exit__()
中被调用。
问题:
是我关于从
__enter__()
和调用acquire()
的假设release()
来自__exit__()
,对吗?我可以看到
__enter__()
和__exit__()
方法在这个例子中做什么?我还注意到,当我在with
版本访问未定义的变量时,我没有得到任何异常(它必须有一些异常处理,简单地抑制错误)。
如即使ppid
和pid
不存在也不会抛出异常
print "#####################"
print "Inside locked semaphore"
print "PPID: %s" % ppid
print "PID: %s" % pid
- 这种使用信号量来确保临界区一个进程的独占性的方法是正确的吗?
- 作为python初学者,我没有抓住为什么
BoundedSemaphore([value])
和Semaphore([value])
在文档中嵌套在class multiprocessing.managers.SyncManager
下,你能澄清这一点吗?
- 是的。
- 您可以在文档中看到这一点(如果只是间接地)。
with
块可以抑制异常,但是信号量的块不应该这样做。也许在multiprocessing
的背景下(或者有(或在2015年)一个bug)有一个复杂的问题。 这是信号量的一种用法,是的。 - 像
SyncManager
下面的Semaphore
这样的名字是创建由管理器支持的同步对象的函数——它们像类一样命名是为了暗示,它们像类一样被调用来制造新对象。