在其他进程准备好之前调用Condition.notify()时,Python多处理死锁

时间:2017-05-19 18:54:56

标签: python concurrency multiprocessing conditional-statements

我有一个生产者和消费者进程,以及它们之间的共享内存区域。当新数据可用时,我使用Condition对象从生产者进程发出消费者进程的信号。

当前问题是cond.wait()上的ArrayConsumer死锁,带有以下跟踪:

Producer: (3, 3, 30, 100)
Producer Done
Consumer: (3, 3, 30, 100)
Consumer Waiting...

根据我的理解,生产者在消费者准备好接收通知之前通知消费者,因此一直等待生产者的通知。确保消费者只有在准备好时才会发出信号的最佳方法是什么?

def ArrayConsumer(aArray, cond):
   print('Consumer:', aArray.shape)

   with cond:
       print('Consumer Waiting...')
       cond.wait()
       print('Waiting finished..')
       print('Consumer:', aArray[1, 1, 1, 1])

def ArrayProducer(aArray, cond):
   print('Producer:', aArray.shape)
   with cond:
       aArray.fill(1)
       cond.notify()
   print('Producer Done')

if __name__ == '__main__':

   # sharing numpy arrays
   csi = csiMatrix(3, 3, 30, 100)
   shared = sm.sharedmem.empty(csi.shape, dtype=complex)
   shared[:] = csi

   cond = Condition()

   p = Process(target=ArrayProducer, args=(shared, cond,))
   c = Process(target=ArrayConsumer, args=(shared, cond,))
   p.start()
   c.start()

   p.join()
   c.join()

1 个答案:

答案 0 :(得分:1)

如果没有人在等待,Condition.notify方法是noop。您需要在while循环中封装逻辑,并定期检查数据是否准备就绪。 Python文档有一个P&C example。您需要为wait方法设置超时,并在每次迭代时检查数组中的数据。

使用LockEvent会更容易避免使用长轮询机制。

def ArrayConsumer(aArray, lock, event):
    print('Consumer:', aArray.shape)
    print('Consumer Waiting...')
    event.wait()
    print('Waiting finished..')
    with lock:
        print('Consumer:', aArray[1, 1, 1, 1])
        event.clear()

def ArrayProducer(aArray, lock, event):
    print('Producer:', aArray.shape)
    with lock:
        aArray.fill(1)
        event.set()
    print('Producer Done')`

尽管如此,我强烈建议使用PipeQueue来实现生产者和消费者模式。这是一个更强大的机制。