Python线程和原子操作

时间:2014-04-17 10:16:58

标签: 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")

但是我已经读过原子操作是线程安全的,在我看来它可以在没有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")

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

1 个答案:

答案 0 :(得分:1)

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

嗯,让我们说在多线程世界中你真的要问:为什么这不应该工作,而是为什么要保证工作

在大多数情况下说多线程在CPython中更容易一些,因为GIL可以保证:

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

请记住,GIL是一个实现细节,如果没有它重写CPython,它可能会消失。

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