我看到使用e.g. here来阻止线程的示例Event
,我认为布尔标志可以完成这项工作。
class MyThread(threading.Thread):
def __init__(self):
self._please_stop = threading.Event()
def run(self):
while not self._please_stop.is_set():
[...]
def stop(self):
self._please_stop.set()
class MyThread(threading.Thread):
def __init__(self):
self._please_stop = False
def run(self):
while not self._please_stop:
[...]
def stop(self):
self._please_stop = True
在这里使用Event
有什么好处?不使用其wait
方法。是什么让它比布尔标志更好?
如果在多个线程之间共享相同的Event
,我可以看到这一点,否则,我无法得到它。
This mailing list thread表示Event
会更安全,但我不明白为什么。
更确切地说,我不理解这两段:
如果我正确理解了GIL,它会同步所有访问权限 Python数据结构(例如我的布尔'终止'标志)。如果说 是这样的,为什么要为此目的使用threading.Event呢?
GIL是一个实现细节,依赖于它来进行同步 适合你的事情不是未来的。你很可能会有很多 警告,但使用threading.Event()并不是更难,而且更多 从长远来看,这是正确和安全的。
我同意使用Event
增加接近没有开销,所以我可以坚持这一点,但我想了解标志方法的局限性。
(我正在使用Python3,所以我不关心Python2的限制,如果有的话,尽管这些在这里完全值得一提。)
答案 0 :(得分:2)
编程通常不仅仅是让代码在今天运行,而是让它继续通过将来会发生的变化。
multiprocessing
...实现Event()
但如果您只使用本地变量则会失败。Semaphore()
而不是Event()
...但很容易用变量错误地实现。所以,很可能你可以在Python中完全正确地编写多线程程序,依赖于字节码如何被中断以及何时可以释放GIL ......但如果我以后正在阅读并更改你的代码,我会更开心如果您使用标准同步原语。
答案 1 :(得分:1)
我认为你引用的主题的含义是设置一个布尔值不一定是Python中的atomic操作。虽然对所有Python对象(GIL)进行全局锁定会使所有设置属性的操作暂时显示为原子,但此类锁定将来可能不存在。使用Event
使操作成为原子操作,因为它使用自己的锁进行访问。
原子的链接是一个Java问题,但由于这个原因,它并没有那么重要。