在 C++ 中轮询原子变量(bool)?

Polling for a atomic variable (bool) in C++?

我有一个修改一个原子变量 (bool) 的线程和另一个想要轮询该变量的线程。我的应用程序在 thread A 中进行了少量函数调用,并开始轮询一个特定的原子变量。 Thread B 继续读取一些外部应用程序 (application on dbus) 的状态并相应地修改几个原子变量。 Thread A 中的一个函数想要确保如果它 returns,那么一些外部应用程序已经将它的状态更改为期望的状态,它将通过这些原子标志获知。

我的申请详情:

thread A中的函数是start_scan()函数,它使用dbus API开始扫描附近的BLE设备。然而,即使 start scan 调用成功但外部应用程序 (org.bluez) 仍然需要一些时间来更新它的属性 (Property: Discovering)。我还定义了像 isScanning 这样的函数,它查询一些变量(我的应用程序内部)以获取外部应用程序的当前状态。每当更新外部应用程序的属性时,它都会通过 dbus 上的 PropertiesChanged 信号通知其他应用程序,是的,在我收到 PropertiesChanged 信号进行扫描之前需要一些时间(不到一秒)成功调用 start_scan。所以,我想在我从 start_scan 函数 return 之前轮询我的本地原子标志(使用我自己的超时机制),这将确保是否有人在调用 [=26= 之后查询扫描状态],那么 isScanning 将 return 一个有效状态。

我不能使用 condition_variable,因为我有很多函数和标志需要在 syn 中。

问题:

std::atomic<bool> scanning_;

// Thread A
void start_scan()
{
    // Dbus methods call
    while (scanning_ == false) { // With some timeout
        // Timeout mechanism
    }
}

// Thread B receving asyn signals from DBus
void propertyUpdate(std::string name, bool value)
{
    if (name == "Discovering")
        scanning_ = value;

    ...
}

当线程 A 将轮询 scanning_ 标志时,线程 B 将收到 dbus 信号以更新 scanning_ 标志。我不确定 Thread A 是否会阻塞线程 B,就好像它会不断读取标志并且我的标志是原子的一样?我想知道如果原子变量可用,等待原子变量访问的线程是如何安排的?

编辑:

我正在做这样的事情:

    void setter(bool value)
    {
        std::lock_guard<std::mutex lock(mutex_);
        member_ = value;
    }

    bool getter(void)
    {
        std::lock_guard<std::mutex lock(mutex_);
        return member_;
    }

    // Thread A is blocking on a class member value
    while (getter() == false);

    // Thread B will modify the class member when required
    setter(true);

我想知道由于在公共互斥锁上调度阻塞线程可能会遇到的问题。线程 A 是否有可能继续获取 mutex_ 而线程 B 将永远被阻塞。如果线程 B 未在线程 A return 中的 getter 函数之后和线程 A 再次获取 mutex_ 之前调度,则可能会发生这种情况。

如果您需要阻塞线程直到条件变为真(在您的情况下,scanning_ 超时),那么您应该使用 condition variables。这样,scanning_ 将只是一个普通变量,而不是原子变量,并且它将受到互斥锁的保护。

(可以使用原子变量进行某些线程通信,但不能仅使用原子变量使线程休眠。在您的示例中,start_scan 不断运行,占用 CPU 时间)