2014-09-30 48 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