如果线程 1 在循环内定期检查 bool 是否从 False 变为 True,并且 bool 在线程 2 中更新,那么是否需要锁?
据我所知,bool 在 python 中是原子的,因此 bool 不可能被错误更新或像在 C++ 中一样采用垃圾值。只有一个线程会更新 bool,并且它只会从 False 变为 True(没有切换回 False 的位置)。由于检查是定期进行的,并且时间并不重要,即使线程 1 在线程 2 将其更新为 True 时读取旧值(False),线程 1 仍然应该能够在线程 2 完成循环的下一次迭代后读取新值。
这是对这种特定情况的错误理解吗?我知道通常最好使用锁,我也不介意添加一个,但我想知道它是否实际上只会引入更多潜在问题(如死锁),而实际上并没有解决任何问题,除了可能将线程 1 从循环中拯救出来以进行一次迭代。
这是有问题的循环。这两个变量在另一个线程中更新,并在此线程中读取。两者都是 bool 值,以 False 开始,并在其他线程完成后设置为 True。
while True:
time.sleep(0.2)
if self.joined_queries:
self.stop()
break
if self.timeout:
self.stop()
break
还有一些其他帖子,但答案非常笼统,没有太多细节,情况也有点不同。我想知道为什么这是一个坏主意!
这份文档让我相信这不是一个问题,但我不确定我是否正确地解释了它:http://www.python.org/doc/faq/library/#what-kinds-of-global-value-mutation-are-thread-safe
实际上,cPython 中的 bool 变量将是指向两个对象之一的指针
Py_True
。Py_False
实现细节并不重要,但重要的是要知道 Python 中的 bool 与 C 中的指针完全一样具有原子性。在没有 GIL 的 cPython 构建中,根据底层 C 代码,这将是一个数据竞争,因此是未定义的行为。
您链接的页面明确指出,由于 GIL,此类代码是安全的,并且正在努力移除 GIL 以提高性能。编写依赖于它的新代码似乎是不明智的。
请注意,C 的未定义行为可能在给定的硬件平台上定义得非常好,只是不可移植。然而,面对较新的解释器和平台,代码会变得脆弱。