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)
这里有两个同步问题.
让我们首先处理一个更容易的事实,即你分享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从队列中使用.
| 归档时间: |
|
| 查看次数: |
293 次 |
| 最近记录: |