线程 1 在循环内定期检查布尔值是否从 False 翻转为 True,并且该布尔值在线程 2 中更新时,是否需要锁?
据我了解,bool 在 python 中是原子的,因此 bool 不应该被错误更新或采用垃圾值,例如在 C++ 中。只有一个线程会更新 bool,并且它只会从 False 变为 True(没有位置切换回 False)。由于检查是定期进行的并且时间并不重要,因此即使线程 1 在线程 2 将旧值 (False) 更新为 True 时读取旧值 (False),一旦线程 2 完成操作,线程 1 仍然应该能够读取新值。循环的下一次迭代。
这是对这个具体情况的错误理解吗?我知道通常最好使用锁,而且我不介意添加一个锁,但我想知道它是否实际上只会引入更多潜在的问题(例如死锁),而实际上不会解决任何问题,除了可能使线程 1 免于循环一个之外更多迭代。
这就是有问题的循环。这两个变量正在另一个线程中更新,并在这个线程中读取。两者都是以 False 开头的布尔值,并在其他线程完成时设置为 True。
while True:
time.sleep(0.2)
if self.joined_queries:
self.stop()
break
if self.timeout:
self.stop()
break
还有一些其他线程,但答案非常笼统,没有详细说明,而且情况有点不同。我想了解为什么这是一个坏主意!
在Python中,当在一个线程中更新布尔变量并在另一个线程中读取它时,建议使用锁来确保线程安全。
原因如下:
避免出现以下问题:
使用锁(例如,
threading.Lock
)同步对布尔变量的访问。
示例:
import threading
class SharedState:
def __init__(self):
self.lock = threading.Lock()
self.flag = False
def set_flag(self):
with self.lock:
self.flag = True
def get_flag(self):
with self.lock:
return self.flag
通过使用锁,您可以确保:
但是,如果您仅在一个方向上更新布尔值(例如,从 False 到 True,但永远不会回到 False),您可以考虑使用
threading.Event
而不是锁。 Event
提供了一种在线程之间发出信号的简单方法,无需锁的开销。
示例:
import threading
class SharedState:
def __init__(self):
self.event = threading.Event()
def set_flag(self):
self.event.set()
def get_flag(self):
return self.event.is_set()
在这种情况下,
Event
确保一旦设置了标志,所有线程都会将其视为已设置。
总结:
threading.Lock
) 进行通用同步。threading.Event
进行单向布尔更新。