Python线程和原子操作

and*_*and 5 python multithreading

我想用同步stop()方法实现一个线程.

我见过这样的版本:

class Thread1:
    def __init__(self):
        self._stop_event = threading.Event()
        self._thread = None

    def start(self):
        self._thread = threading.Thread(target=self._run)
        self._thread.start()

    def stop(self):
        self._stop_event.set()
        self._thread.join()

    def _run(self):
        while not self._stop_event.is_set():
            self._work()

    def _work(self):
        print("working")
Run Code Online (Sandbox Code Playgroud)

但我已经读过原子操作是线程安全的,在我看来它可以在没有的情况下完成Event.所以我想出了这个:

class Thread2:
    def __init__(self):
        self._working = False
        self._thread = None

    def start(self):
        self._working = True
        self._thread = threading.Thread(target=self._run)
        self._thread.start()

    def stop(self):
        self._working = False
        self._thread.join()

    def _run(self):
        while self._working:
            self._work()

    def _work(self):
        print("working")
Run Code Online (Sandbox Code Playgroud)

它认为在C中类似的实现被认为是不正确的,因为编译器可以放入_working寄存器(甚至优化),工作线程永远不会知道变量已经改变.可以在Python中发生类似的事情吗?这个实现是否正确?我的目的不是完全避免事件或锁定,只是想了解这个原子操作的事情.

jb.*_*jb. 2

据我所知,它在Python中也是不正确的,因为_working仍然可以放入寄存器或以其他方式优化,或者可能会发生其他一些事情来改变它的值。处理器可以对该字段进行任意重新排序。

好吧,可以说,在多线程世界中,您不应该真正问:为什么这不起作用,而应该问为什么这保证能起作用

话虽如此,在大多数情况下,CPython 中的多线程会更容易一些,因为GIL保证了:

  • 在任何给定时间仅执行一个解释器命令。
  • 通常强制线程之间进行内存同步。

请记住,GIL 是一个实现细节,如果有人在没有它的情况下重写 CPython,那么它可能会消失。

另请注意,它应该在任何实际系统中以这种方式实现。