线程内试图停止自身导致的竞态条件
引发的原因很简单:在一个服务线程内,试图调用停止自身的方法并 join 导致死锁,进而导致线程被阻塞,服务无法正常退出。
伪代码如下:
import threading
class Service:
def __init__(self, message_handler):
self._message_handler = message_handler
self._stop_event = threading.Event()
self._server_thread = threading.Thread(target=self._start_server)
def _start_server(self):
while not self._stop_event.is_set():
# 收到客户端的 message,在回调中处理
self._message_handler(message)
def start(self):
self._server_thread.start()
def stop(self):
self._stop_event.set()
self._server_thread.join()
def message_handler(message):
if message == "stop":
service.stop() # <-- 这里会导致死锁!
if __name__ == "__main__":
service = Service(message_handler)
service.start()
这段代码比较迷惑人的一点是,在实际项目中,Service 往往是在单独的模块中,而被传入的 message_handler 则是在 Service 的调用方。这就容易让人误以为 message_handler 是在调用 Service 的线程执行,但实际是在 Service 自身运行的线程中执行。
由于 message_handler 中调用了 Service.stop
,这个方法中又 join 了 Service 所在的线程,从而导致死锁(join 要等到 Service 所在线程结束后返回,但 Service 所在线程又需要等到 join 调用完成后才能结束)。