如何使用std::atomic_bool或std::atomic_flag?

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

嗨,我需要在程序的回调函数中使用布尔标志来控制程序行为。回调线程在与设置它们的线程不同的线程中执行。在我的一个回调函数中,程序设置布尔标志,而在另一个回调函数中,它检查不同的不相关的布尔标志。目前我正在使用 std::atomic_bool 来实现此目的。

我读过有关 std::atomic 变量发生死锁的可能性的信息。就我而言,这是值得担心的事情吗?还有什么需要担心的吗?

我在使用atomic_bool像普通变量一样正确地做事吗?如果不是我该怎么办?

我应该使用 std::atomic_flag 来代替吗?

并且编译器在类成员列表中初始化standbyResumeTimerDelayBool时没有抛出错误,不确定这是否正确。

谢谢!

//some code omitted to keep things simple
//first callback function, this boolean flag is checked at one other point in the program
static ULONG Replicator::standbyResumeCallbackFunction(PVOID context, ULONG type, PVOID setting);
ULONG Replicator::standbyResumeCallbackFunction(PVOID context, ULONG type, PVOID setting)
{
    if (type == PBT_APMRESUMEAUTOMATIC)
    {
        Replicator* replicator = reinterpret_cast<Replicator*>(context);
        replicator->standbyResumeSetTimerDelayBool();
    }
}

//Replicator class members
void standbyResumeSetTimerDelayBool() { standbyResumeTimerDelayBool = true; }
std::atomic_bool standbyResumeTimerDelayBool = false;

//behavior modified here
void Replicator::autoBackup()
{
    if (standbyResumeTimerDelayBool)
    {
        standbyResumeTimerDelayBool = false;
        //do stuff
    }
}


//second callback function
static DWORD CALLBACK copyProgress(
             LARGE_INTEGER totalSize, LARGE_INTEGER totalTransferred,
             LARGE_INTEGER streamSize, LARGE_INTEGER streamTransferred,
             DWORD streamNo, DWORD callbackReason, HANDLE src, HANDLE dst,
             LPVOID data);

DWORD Worker::copyProgress(LARGE_INTEGER totalSize, LARGE_INTEGER totalTransferred, LARGE_INTEGER, LARGE_INTEGER, DWORD, DWORD, HANDLE, HANDLE, LPVOID data)
{
    Worker *worker = static_cast<Worker *>(data);

    if (worker->getStop())
        return PROGRESS_CANCEL;
}

//Worker class members
bool getStop() { return cancel; }
std::atomic_bool cancel;

//cancel is set to false when backup begins
void Worker::startBackup()
{
    cancel = false;
}
//if user clicks cancel button cancel flag is set to false
void stop() { cancel = true; }
c++ multithreading thread-safety atomic
1个回答
0
投票

我读过有关 std::atomic 变量发生死锁的可能性的信息。就我而言,这是值得担心的事情吗?

std::atomic
本身永远不会陷入僵局。

我在使用atomic_bool像普通变量一样正确做事吗?

是的,这就是

std::atomic
的重点,让使用原子就像使用普通变量一样简单。

我应该使用 std::atomic_flag 来代替吗?

为什么?

std::atomic_flag
有一个比
std::atomic_bool
更复杂的接口,并且检查速度更慢,因为它只能通过RMW操作来检查,它被用作互斥体的构建块,而不是作为原子布尔值。


我唯一有效的评论是在这一行。

if (standbyResumeTimerDelayBool)
    {
        standbyResumeTimerDelayBool = false;
        //do stuff
    }

如果有多个线程同时执行此操作,则可能有多个线程最终执行此块,而您应该在此处进行交换

if (standbyResumeTimerDelayBool && !standbyResumeTimerDelayBool.exchange(true))
{
 // only 1 thread can enter this block
}

但请注意,此交换比正常写入慢,因此如果只允许 1 个线程执行此代码,那么您的原始代码就可以了。

© www.soinside.com 2019 - 2024. All rights reserved.