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

时间:2015-09-01 20:50:44

标签: python multithreading python-multiprocessing

Here我发现以下示例(这是修改后的版本)使用信号量与多处理模块:

#!/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模块中,这些方法是AFAIK,相当于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()

从我之前的question开始,我了解到当某个方法与with关键字一起使用时,会在进入时调用上下文管理器的__enter__()__exit__()方法(和分别从with语句的正文退出。因此,我假设在acquire()内调用__enter__(),在release()内调用__exit__()

问题:

  1. 我的假设是从acquire()__enter__()调用release() 来自__exit__()的{​​{1}}正确吗?

  2. 我能否以某种方式查看此示例中__enter__()__exit__()方法的用途?我还注意到,当我在with版本中访问未定义的变量时,我没有得到任何异常(必须有一些异常处理才能简单地抑制错误)。

  3. E.G。即使ppidpid不存在,这个也不会抛出异常

    print "#####################"
    print "Inside locked semaphore"
    print "PPID: %s" % ppid
    print "PID:  %s" % pid
    
    1. 这种使用信号量的方法是否确保关键部分中某个流程的排他性是正确的?
    2. 作为一名蟒蛇初学者,我没有理解为什么BoundedSemaphore([value])Semaphore([value])嵌套在documentationclass multiprocessing.managers.SyncManager下,你可以澄清一下吗?

1 个答案:

答案 0 :(得分:0)

  1. 是的。
  2. 您可以在the documentation中看到(如果只是间接看到的话)。 with可以抑制异常,但信号量的块不应这样做。可能是multiprocessing的背景下(或(或曾在2015年)有一个错误)。
  3. 是信号灯的用途之一。
  4. Semaphore下的SyncManager之类的名称是用于创建由管理器支持的同步对象的函数-它们像类一样被命名,以暗示它们像类一样被调用来制造新对象。