用获取和释放信号量方法代替关键字



在这里,我发现了以下使用多处理模块信号量的例子(这是修改后的版本):

#!/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的threadingmultiprocessing模块中,这些方法完全等同于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__()中被调用。

问题:

  1. 是我关于从__enter__()和调用acquire()的假设release()来自__exit__(),对吗?

  2. 我可以看到__enter__()__exit__()方法在这个例子中做什么?我还注意到,当我在with版本访问未定义的变量时,我没有得到任何异常(它必须有一些异常处理,简单地抑制错误)。

如即使ppidpid不存在也不会抛出异常

print "#####################"
print "Inside locked semaphore"
print "PPID: %s" % ppid
print "PID:  %s" % pid
  • 这种使用信号量来确保临界区一个进程的独占性的方法是正确的吗?
  • 作为python初学者,我没有抓住为什么BoundedSemaphore([value])Semaphore([value])在文档中嵌套在class multiprocessing.managers.SyncManager下,你能澄清这一点吗?
    1. 是的。
    2. 您可以在文档中看到这一点(如果只是间接地)。with可以抑制异常,但是信号量的块不应该这样做。也许在multiprocessing的背景下(或者有(或在2015年)一个bug)有一个复杂的问题。
    3. 这是信号量的一种用法,是的。
    4. SyncManager下面的Semaphore这样的名字是创建由管理器支持的同步对象的函数——它们像类一样命名是为了暗示,它们像类一样被调用来制造新对象。

    相关内容

    最新更新