在python中同步2个线程

时间:2014-09-30 08:48:06

标签: python multithreading

我在同步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()

我希望看到的输出如下:A B A B A B A B A B ...,以便主线程通过生成' 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()

2 个答案:

答案 0 :(得分:2)

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

你可以做两件事:

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

答案 1 :(得分: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'

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

由于