Python线程和原子操作
问题内容:
我想用同步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中发生吗?这个实施正确吗?我并不是要完全避免发生事件或锁定,只是想了解这种原子操作的事情。
问题答案:
据我所知,它在Python中也是不正确的,_working
仍然可以通过其他方式进行注册或优化,否则可能会发生其他事情,从而改变其价值。对该字段的读写可以由处理器任意重新排序。
好吧,可以说在多线程世界中,您实际上 不会 问: 为什么这不起作用 ,而是 为什么要保证它起作用 。
话虽这么说,在大多数情况下,由于GIL保证了:
- 在任何给定时间仅执行一个解释器命令。
- 经常强制线程之间进行内存同步。
请记住,GIL是实现细节,如果有人在没有它的情况下重写CPython,它可能会消失。
还应注意,它 应该 在任何实际系统中都以这种方式实现。