python中的基本线程

时间:2013-06-03 21:09:06

标签: python multithreading python-multithreading

确定代码非常基本。由于我使用多个线程,并且我想要它们之间的共享变量,我使用的是全局。

当我点击“C”时,为什么ThreadClass中的代码有时不会执行?我知道这是一个并发问题,但我不确定如何解决它。我已经阅读了信号量并最近锁定了,但我现在还不确定如何实现它。 欢迎任何建议。

import threading
buff_list = []

class ThreadClass(threading.Thread):
    global buff_list
    def run(self):
        while (True):
            if ("C" == raw_input()):
                buff_list.append("C")
                print buff_list

class ThreadClass2(threading.Thread):
    global buff_list
    def run(self):
        while(True):
            if ("B" == raw_input() and len(buff_list) > 0):
                buff_list.pop()
                print buff_list

a = ThreadClass()
b = ThreadClass2()

a.start()
b.start()

3 个答案:

答案 0 :(得分:6)

这里有两个同步问题。

让我们首先处理更容易的事情,即您分享两个线程争夺的全局buff_list这一事实。没有什么能阻止一个线程同时尝试append其他线程pop,这是非法的。而且,即使你很幸运并且没有发生,pop也可以在<{em> append之前来。


解决此问题的最简单方法是使用Queue,它会自动同步:

buff_list = Queue.Queue()

然后只使用put代替appendget代替pop


但是,如果你想自己学习这些东西,可以采用两种方法。

首先,您可以使用Lock。 (您也可以使用RLock,但暂时忘记这一点。)这可以确保一次只有一个线程访问buff_list

buff_lock = threading.Lock()
buff_list = []

现在,每当你追加或弹出时,只需抓住锁:

with buff_lock:
    buff_list.append("C")

with buff_lock:
    val = buff_list.pop()

但是这不会确保弹出的代码等到有东西出现。如果您想这样做,请使用Condition

buff_cond = threading.Condition()

现在:

with buff_cond:
    buff_list.append("C")
    buff_cond.notify()

with buff_cond:
    while not buff_list:
        buff_cond.wait()
    value = buff_list.pop()

第二个问题是您隐式共享sys.stdin,因为两个线程都在调用raw_input。除非你有某种方法来同步事物,以便每个线程都知道它应该何时获得下一个输入(并且可能很难描述,如果可以的话,你可以将它变成代码&# 39;描述它),这可能是有效的 - 每次你输入C时,错误的线程都会有50/50的机会获得它。

因此,正如kirelagin建议的那样,你需要只为一个线程负责I / O.最简单的方法是再次使用Queue,并使一个线程put任何它不使用的输入,另一个线程可以从队列中get

答案 1 :(得分:4)

嗯,你永远不知道哪个类的实例得到了你的输入。如果您点击“C”并且ThreadClass2正在阅读您的输入,则只有"B" == raw_input() False才会执行任何操作。

一个线程应该负责I / O.

答案 2 :(得分:0)

除了之前的回复中所说的内容之外,我还想补充一点,线程模块还支持在所有其他语言中实现的更原始的机制,例如Semaphore Objects

这是计算机科学史上最古老的同步原语之一,由荷兰早期计算机科学家Edsger W. Dijkstra发明(他使用P()和V()而不是获取()和释放( ))。

我认为深入学习线程的最佳方法是从头开始。