Python Consumer-Producer。制片人等待消费者消费

时间:2014-06-04 20:15:16

标签: python multithreading

我想要完成2项任务。一个是生产者,另一个是消费者。生产者必须等待消费者使用数据才能生成新数据。执行流程必须是:fpga,bbb,fpga,bbb,fpga,bbb,fpga,bbb,fpga,bbb ..... 当我有一个很大的睡眠时间为生产者每个人工作正常,但当睡眠时间很短我有一个僵局。 ¿有谁知道为什么?我的代码:

class fpga (threading.Thread):
            def __init__(self,condition,data):
                    threading.Thread.__init__(self)
                    self.name='fpga'
                    self.condition=condition
                    self.data=data
                    self.sleepTime=1.0/(300.0*18.0) 
                    self.count=0
            def run(self):
                    while True:
                            newData='YxxY'
                            self.condition.acquire()
                            self.condition.notify()
                            self.condition.wait()
                            self.condition.release()

                            time.sleep(self.sleepTime) #sleep some time
                            print 'fpga'

    class bbb (threading.Thread):
            def __init__(self,condition,data):
                    threading.Thread.__init__(self)
                    self.name='bbb'
                    self.condition=condition
                    self.data=data
            def run (self):
                    while True:
                            self.condition.acquire()
                            self.condition.wait()
                            self.condition.notify()
                            self.condition.release()
                            print 'bbb'
    if __name__=='__main__':
            dataFpga=[]     
            dataFromFpgaCondition=threading.Condition()     
            threadfpga=fpga(dataFromFpgaCondition,dataFpga)
            threadBbb=bbb(dataFromFpgaCondition,dataFpga)
            threadBbb.start()
            threadfpga.start()
            threadBbb.join()
            threadfpga.join()

2 个答案:

答案 0 :(得分:3)

你的代码中有一场比赛。

您的制作人fpga,需要执行以下操作:

  1. acquire condition锁定
  2. 提供一些新数据(不清楚示例代码中会发生什么)
  3. notify另一个帖子
  4. release condition锁定
  5. 消费者bbb需要执行以下操作:

    1. acquire condition锁定
    2. wait通知数据可用(重要:这会释放锁定)
    3. 对数据执行某些操作
    4. notify已完成处理的制作人
    5. release condition锁定
    6. 您的消费者正在完成上面列出的步骤:

      self.condition.acquire()  # Step 1
      self.condition.wait()  # Step 2
      self.condition.notify()  # Step 4 (step 3 is left out here, but its not important)
      self.condition.release() # Step 5
      

      但是,您的制作人没有遵循以下步骤:

      self.condition.acquire() # Step 1
      self.condition.notify() # Step 2
      self.condition.wait() # This isn't a step! And we're releasing the lock when we do it!
      self.condition.release() # Step 4 (no step 3 again, but that's ok)
      

      在致电wait后,您会立即拨打notify电话。这引入了竞争条件。你最终可以得到这个:

      bbb.condition.acquire()
      bbb.condition.wait() # This releases the lock and then blocks, waiting to be notified
      fpa.condition.acquire()
      fpga.condition.notify()
      fpga.condition.wait() # bbb acquires the lock right after this, because it's in wait()
      bbb.condition.notify()
      bbb.condition.release() # fpga.wait() now completes
      fpga.condition.release() # Ok, both threads just called release. Now it's race.
      fpga.condition.acquire() # The producer won the race. This is bad.
      fpga.condition.notify()
      fpga.condition.wait() # Releases the lock and waits
      bbb.condition.acquire()
      bbb.condition.wait() # No they're both waiting, and you're deadlocked.
      

      你可以通过添加sleep来避免这种情况,因为一旦我们到达比赛点,制作人就会暂停sleep,这会让消费者获胜。如果没有睡眠,或者睡眠时间很短,生产者就可以获胜。

      修复只是删除生产者对self.condition.wait()的调用。

答案 1 :(得分:0)

两个线程wait可能是另一个,例如以下时间表

fpga.acquire
fpga.notify
fpga.wait
bbb.acquire
bbb.wait

是可能的,并且很快就会导致死锁。

您的方法不起作用,因为notify未被“记住”,如果执行notify时没有等待线程,则通知将丢失。