gpt4 book ai didi

C++ 可以在结构内声明原子变量以保护这些成员吗?

转载 作者:可可西里 更新时间:2023-11-01 14:39:27 25 4
gpt4 key购买 nike

在共享文件中声明和定义结构。

Windows API CreateThread() 创建的两个线程都可以看到它的实例:

struct info
{
std::atomic<bool> inUse;
string name;

};
info userStruct; //this guy shared between two threads

线程 1 持续锁定/解锁以写入 到结构中的成员(测试值相同):

    while (1)
{
userStruct.inUse = true;
userStruct.name= "TEST";
userStruct.inUse = false;
}

线程 2 只是读取 和打印,只有当它碰巧发现它已解锁时

    while (1)
{
while (! userStruct.inUse.load() )
{
printf("** %d, %s\n\n", userStruct.inUse.load(), userStruct.name.c_str());
Sleep(500); //slower reading
}

printf("In Use!\n");
}

希望看到很多:

"In Use!"

每一次,如果它进入,解锁时:

"0, TEST"

..确实如此。

但也看到了:

"1, TEST"

如果 atomic bool 是 1,我不希望看到它。

我做错了什么?

最佳答案

您的代码不是线程安全的。原子就是原子。但是 if 语句不是!

发生了什么:

Thread 1                                Thread 2               Comment 

while (! userStruct.inUse.load() ) ---> InUse is false
==> continues loop
inUse = true
==> continues loop already started
printf(...)

在最坏的情况下,您可能会因为数据竞争而出现 UB(线程 2 修改字符串,线程 1 在修改期间读取字符串)。

解决方案:

由于您打算将原子用作锁,只需使用为这种同步设计的真正锁,使用 std::mutexstd::lock_guard .

例如:

struct info
{
std::mutex access;
string name;
};

第一个线程将是:

while (1)
{
std::lock_guard<std::mutex> lock(userStruct.access); // protected until next iteration
userStruct.name= "TEST";
}

然后第二个线程可以尝试以非阻塞方式访问互斥量:

while (1)
{
{ // trying to lock the mutex
std::unique_lock<std::mutex> lock(userStruct.access, std::try_to_lock);
if(!lock.owns_lock()){ // if not successful do something else
std::cout << "No lock" <<std::endl;
}
else // if lock was successfull
{
std::cout << "Got access:" << userStruct.name <<std::endl;
}
} // at this stage, the lock is released.
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}

Online demo

关于C++ 可以在结构内声明原子变量以保护这些成员吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53366243/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com