2014-09-30 36 views
1

我在同步2个线程时遇到很大困难。每个线程都依赖于另一个线程的结果。比方说,我有以下代码:在python中同步2个线程

from multiprocessing import Condition, Process 
import time 

def B_producer(new_A,new_B): 
    while True: 
     with new_A: 
      new_A.wait() 

     with new_B: 
      print 'B', 
      new_B.notify_all() 


if __name__=='__main__': 
    new_A = Condition() 
    new_B = Condition() 

    B_producer = Process(target=B_producer, args=(new_A,new_B)) 
    B_producer.start() 

    time.sleep(2) 

    while True: 
     with new_A: 
      print 'A', 
      new_A.notify() 


     with new_B: 
      new_B.wait() 

我想看到的是一个输出,如:ABABABABA乙......,所以,主线程通过生成一个“A”开头,而另一个是等待。一旦产生了'A',它就等待'B'。同时,辅助线程则相反。不能重复字母。不幸的是,我找不到如预期的那样工作的方法。

编辑:鉴于第一个答案的讨论中,我改变了代码,以使其更清晰,程序死锁进入永不终止:

from multiprocessing import Condition, Process 
import time 

def B_producer(new_A,new_B): 
    while True: 
     with new_A: 
      new_A.wait() 

     with new_B: 
      #do something 
      new_B.notify_all() 


if __name__=='__main__': 
    new_A = Condition() 
    new_B = Condition() 

    B_producer = Process(target=B_producer, args=(new_A,new_B)) 
    B_producer.start() 

    time.sleep(2) 

    count = 0 

    while True: 
     with new_A: 
      #do something 
      new_A.notify() 


     with new_B: 
      new_B.wait() 

     count += 1 
     if count == 1000000: 
      break 

    B_producer.terminate() 
    sys.stdout.write('end') 
    sys.stdout.flush() 

回答

0

我觉得我有一个解决方案,即使可能会更简单。为了避免在B_producer准备好之前启动主循环并等待主线程完成它,我添加了一个开始条件。我还必须添加一个额外的锁来防止竞争条件的new_A条件。

def B_producer(new_A,new_B,synch,start): 
    synch.acquire() 
    while True: 
     with new_A: 
      synch.release() 
      with start: 
       start.notify() 
      new_A.wait() 

      with new_B: 

       #Do something 

       synch.acquire() 
       new_B.notify() 

if __name__=='__main__': 
    new_A = Condition() 
    new_B = Condition() 
    start = Condition() 
    synch = Lock() 

    B_producer = Process(target=B_producer, args=(new_A,new_B,synch,start)) 
    with start: 
     B_producer.start() 
     start.wait() 

    count = 0 

    synch.acquire() 

    while True: 
     new_A.acquire() 
     synch.release() 

     #Do something 

     with new_B: 
      new_A.notify() 
      new_A.release() 

      new_B.wait() 
      synch.acquire() 

     count += 1 
     if count%100000 == 0: 
      break 

    B_producer.terminate() 
    print 'end' 

如果有人发现更好/更简单的解决方案,请发布它!

谢谢

2

你的代码的工作,唯一的事情您是否遇到print "A/B",的一些问题。这里的问题是print后的逗号。它可以防止打印后发生换行,但打印语句无法更新控制台上已写入的行,但只能写入单行。因此,它将所有内容存储在缓冲区中,直到执行print换行符,然后写入整行。

你可以做两件事情:

  • print后删除逗号(这将导致在单独一行上打印的每一个字母)。
  • 或者,如果您希望将它们写入同一行,可以使用sys.stdout.write('A/B '),然后按sys.stdout.flush()(以保持输出更新)。不要忘记import sys
+0

修改显示打印出现问题,但程序在一些迭代后仍然进入死锁状态。 – 2014-09-30 12:51:48

+0

我认为这是因为在太短的时间内显示电脑太多,所以它只是停止。如果你在'print'或者'sys.stdout.flush()'之后加上'time.sleep(0.01)',它会永远运行。 – 2014-09-30 13:08:27

+0

我希望你这次也是对的,但是,不要打印'A'或'B',而是在主线程上使用计数器,并在每个循环中增加计数器。例如,当计数值达到10000时,打破循环并打印一些内容。它仍然会进入死循环,永远不会出现在循环中。 – 2014-09-30 13:45:30