python中的基本线程

use*_*969 5 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()
Run Code Online (Sandbox Code Playgroud)

aba*_*ert 6

这里有两个同步问题.

让我们首先处理一个更容易的事实,即你分享buff_list两个线程争夺的全局.没有什么能阻止一个线程同时尝试append其他线程pop,这是非法的.而且,即使你得到幸运,这并没有发生,pop能来之前append.


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

buff_list = Queue.Queue()
Run Code Online (Sandbox Code Playgroud)

然后,只需使用put的,而不是append和,get而不是pop.


但是,如果你想自己学习这些东西,有两种可能的方法.

首先,你可以使用Lock.(你也可以使用RLock,但是现在让我们忘记它.)这确保一次只能访问一个线程buff_list.

buff_lock = threading.Lock()
buff_list = []
Run Code Online (Sandbox Code Playgroud)

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

with buff_lock:
    buff_list.append("C")

with buff_lock:
    val = buff_list.pop()
Run Code Online (Sandbox Code Playgroud)

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

buff_cond = threading.Condition()
Run Code Online (Sandbox Code Playgroud)

现在:

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

with buff_cond:
    while not buff_list:
        buff_cond.wait()
    value = buff_list.pop()
Run Code Online (Sandbox Code Playgroud)

第二个问题是你隐式共享sys.stdin,因为两个线程都在调用raw_input.除非你有某种方法来同步事物,以便每个线程知道什么时候它应该得到下一个输入(并且可能很难描述,如果你不能描述它就不能把它变成代码),不可能工作 - 每次你键入时C,错误的线程将有50/50的机会获得它.

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

  • @kirelagin:嗯,是的,解决任何编码问题的最简单方法就是不写任何代码...... (2认同)