停止一个主题:标志与事件

Jér*_*ôme 7 python python-multithreading

我在这里看到了一些示例,例如使用一个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()
Run Code Online (Sandbox Code Playgroud)

 旗

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
Run Code Online (Sandbox Code Playgroud)

Event在这里使用一个有什么好处?它的wait方法没有使用.是什么让它比布尔标志更好?

如果Event在多个线程之间共享相同的内容,我可以看到这一点,否则,我不明白.

这个邮件列表线程表明它Event会更安全,但我不明白为什么.

更准确地说,我不明白这两段:

如果我正确理解了GIL,它会同步对Python数据结构的所有访问(例如我的布尔'终止'标志).如果是这种情况,为什么还要为此目的使用threading.Event呢?

GIL是一个实现细节,依靠它来为您同步事物不是未来的.你可能会有很多警告,但使用threading.Event()并不是更难,而且从长远来看它更正确,更安全.

我同意使用Event添加几乎没有开销,所以我可以坚持,但我想了解标志方法的局限性.

(我正在使用Python3,所以我不关心Python2的限制,如果有的话,尽管这些在这里完全值得一提.)

gz.*_*gz. 5

编程通常不仅是让代码在今天正常工作,还在于在未来进行的更改中保持代码正常工作。

  • 其他 Python 实现没有 GIL。我明天要在pypy上运行它吗?
  • 实际上,我需要将工作分散到多个流程中。Swap in multiprocessing...Event()如果您只是使用局部变量,它会实现但会失败。
  • 事实证明,只有在其他几个线程认为应该停止时,代码才应该停止。好吧,使用Semaphore()而不是Event()...但是很容易用变量错误地实现。

因此,您很可能可以在 Python 中完全正确地编写多线程程序,这取决于字节码如何中断以及 GIL 何时可以发布……但是如果我稍后阅读并更改您的代码,如果您使用,我会更高兴标准同步原语。


Mad*_*ist 2

我认为你引用的线程中的含义是设置布尔值不一定是Python中的原子操作。虽然对所有 Python 对象(GIL)使用全局锁使得所有设置属性的操作暂时看起来是原子的,但这样的锁将来可能不存在。使用Event使操作原子化,因为它使用自己的锁进行访问。

atomic 的链接是一个 Java 问题,但它的相关性也并没有因此降低。