【问题标题】:Is it possible to prioritise a lock?是否可以优先考虑锁定?
【发布时间】:2017-01-08 07:20:12
【问题描述】:

我有一个multiprocessing 程序,其中

  • 一个进程将元素添加到共享列表 (multiprocessing.Manager().list())
  • 其他几个进程使用该列表中的这些元素(并删除它们);它们会一直运行,直到列表中有要处理的内容,并且上面的过程仍在添加到列表中。

在添加到列表或从中删除时,我实现了锁定(通过multiprocessing.Lock())。由于有一个“feeder”进程和几个(10-40)个“consumer”进程都在争夺锁,而且消费者进程很快,所以我最终发现“feeder”进程很难获得锁。

获取锁时是否有“优先级”的概念?我希望“feeder”进程以比其他进程更高的优先级获取它。

现在我通过让“消费者”进程在尝试获取锁之前等待随机时间来缓解这个问题,而“馈送”进程在那里(当它结束时它会设置一个标志)。这是一种可行的解决方法,但它很难看并且几乎没有效果(我让进程等待random.random()*n 秒,其中n 是进程数。这是一个完全虚构的数字,可能是错误的)。

【问题讨论】:

  • “队列”的概念是如何实现的?当他们来锁定时,您是否只是将进程附加到列表中?
  • @Ev.Kounis:是的,这是我在问题中提到的multiprocessing.Manager().list()(这不是multiprocessing.Queue()
  • 出于好奇,您是否尝试过使用multiprocessing.Queue 而不是实现它?
  • 如果您只有一个喂食器,就不应该存在竞争条件。只需 put 到队列或 append 到列表。消费者应该从队列中get 或从列表中pop(0)。根据文档,“队列是线程和进程安全的。”即,您不需要在馈线端或消费者端锁定。你最好使用Queue。如果您想继续使用Manager().list,因为您只是从列表中弹出,而不是修改其中的值,我认为您也不需要锁。让multiprocessing 模块完成它的工作。
  • 您需要"reader writer lock"。您可以使用两个锁和一个计数器来实现它(阅读链接)。

标签: python python-3.x multiprocessing python-multiprocessing


【解决方案1】:

它并不完美,但它必须有效:

在“馈线”中:

feeder_lock_object.lock()
consumer_lock_object.lock()
try:
    ...
finally:
    feeder_lock_object.release()
    consumer_lock_object.release()

在“消费者”中:

while True:
    with consumer_lock_object:
        if feeder_lock_object.is_locked:
            continue
        ...

但我认为使用队列会更好。

如果您使用此方法,请注意如何实现锁定对象。您应该使用将这些锁定对象创建为全局参数的初始化函数来初始化池。参考this

【讨论】:

    【解决方案2】:

    与其尝试更改锁定优先级,不如尝试更改进程优先级本身,使馈送者的优先级高于消费者。您使用的解决方法基本上模拟了这一点,但效率较低。

    要更改进程优先级,

    在 Unix 上:使用 os.setpriority()

    请参考docs

    在 Windows 上,使用第三方模块 psutil。

    请参阅this threadPsutil Docs

    【讨论】:

      【解决方案3】:

      使Feeder的获取锁阻塞,而consumer的非阻塞。
      所以对于馈线:

      try:
          with my_lock.acquire(): #locks block by default
              do stuff
      finally:
          my_lock.release()
      

      还有消费者:

      while True:
         try:
            locked = my_lock.acquire(blocking=False)
            if locked:
               do stuff
         finally:
            if locked:
               my_lock.release()
         time.sleep(seconds=10)
      

      【讨论】:

        猜你喜欢
        • 2017-11-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-02
        • 2010-10-27
        • 1970-01-01
        • 2022-11-28
        相关资源
        最近更新 更多