在Python中,当在线程中向一个方向更新布尔值,然后在另一个方向读取它时,是否建议使用锁?

问题描述 投票:0回答:1

线程 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 python-3.x multithreading python-multithreading race-condition
1个回答
0
投票

在Python中,当在一个线程中更新布尔变量并在另一个线程中读取它时,建议使用锁来确保线程安全。

原因如下:

  1. 原子性:Python 中的布尔运算不是原子性的。这意味着更新布尔变量涉及多个步骤(读取、修改、写入),这可能会导致竞争条件。
  2. 可见性:由于缓存或编译器优化,一个线程所做的更改可能不会立即对其他线程可见。

避免出现以下问题:

  • 读取陈旧值
  • 缺少更新
  • 引入微妙的错误

使用锁(例如,

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

通过使用锁,您可以确保:

  1. 一次只有一个线程可以修改或读取布尔变量。
  2. 所有线程都可以立即看到更改。

但是,如果您仅在一个方向上更新布尔值(例如,从 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
    进行单向布尔更新。
© www.soinside.com 2019 - 2024. All rights reserved.