我读过https://en.cppreference.com/w/cpp/atomic/atomic/compare_exchange
原子地比较*的对象表示(直到C++20)值表示(自C++20)和预期的值表示,如果它们是按位相等的,则用所需的(执行读-修改-写入操作)替换前者。否则,将存储在*中的实际值加载到预期中(执行加载操作)。
所以,据我所知,代码就像
bool expected=true;
extern atomic<bool> b = false;
void foo ()
{
//
while(!b.compare_exchange_weak(expected, false));
//
}在循环运行一次(忽略虚假失败)之后,它将失败,并将写入预期的false,因此在第二次迭代中,compare_exchange_weak将返回成功,尽管b尚未更改为true。但这一切有什么意义?我想我可以用它作为同步锁,等待其他线程更改b,但是现在我想不出它的用法了。
Cp首选项中的示例还显示,在两个调用之后,compare_exchange_strong将成功。
#include <atomic>
#include <iostream>
std::atomic<int> ai;
int tst_val= 4;
int new_val= 5;
bool exchanged= false;
void valsout()
{
std::cout << "ai= " << ai
<< " tst_val= " << tst_val
<< " new_val= " << new_val
<< " exchanged= " << std::boolalpha << exchanged
<< "\n";
}
int main()
{
ai= 3;
valsout();
// tst_val != ai ==> tst_val is modified
exchanged= ai.compare_exchange_strong( tst_val, new_val );
valsout();
// tst_val == ai ==> ai is modified
exchanged= ai.compare_exchange_strong( tst_val, new_val );
valsout();
}结果:
ai= 3 tst_val= 4 new_val= 5 exchanged= false
ai= 3 tst_val= 3 new_val= 5 exchanged= false
ai= 5 tst_val= 3 new_val= 5 exchanged= true发布于 2021-03-05 14:30:40
我将给出一个例子,因为它非常简单,所以我确实使用了它。
我有原子,它描述了某种东西的可用大小。存在整数溢出的危险,所以我必须先进行检查,然后再减去一个值。
不完全复制我的生产代码:
class LockFreeCuncuretSizeLimit {
public:
explicit LockFreeCuncuretSizeLimit(size_t available) : mSize{available}
{}
bool tryAcuqire(size_t s) {
size_t lastSize = mSize;
size_t newSize;
do
{
if (lastSize >= s)
{
newSize = lastSize - s;
}
else
{
return false;
}
}
while (!mSize.compare_exchange_weak(lastSize, newSize));
return true;
}
void release(size_t s) {
mSize += s; // here I do not have worry about integer overflow
}
private:
std::atomic<size_t> mSize;
};现在,尝试映像,这样做,没有compare_exchange_strong和没有种族条件。
有一个条件是满足的,但是当对原子执行减法时,其他一些线程已经减去了一个值,所以当我执行实际减法时,就有可能溢出整数。因此,如果没有compare_exchange_strong,就无法做到这一点。
现在,compare_exchange_strong和compare_exchange_weak之间的区别很难解释。即使是Herb在一些cppcon谈话中也放弃了解释,并提供了简单的规则:“如果您需要循环,请使用compare_exchange_weak,否则使用compare_exchange_strong”。
发布于 2021-03-05 14:40:12
std::atomic::compare_exchange_weak以线程感知的方式执行此英语任务:
,因为变量包含
expected,所以它现在应该保存desired。
作为一个琐碎的任务,,假设您的std::atomic<int> x的值应该是平方。但是其他线程可能正在修改它,所以您不能简单地读取值、调整值并将新值写回。在你读完它后,它的值可能已经改变了!
下面是执行此任务的线程安全方法。您可以保证存储的值将被替换为其平方。
int expected = x;
while( !x.compare_exchange_weak(expected, expected*expected) );此代码将原子化地将expected替换为其平方,除非值已更改。
如果值已更改,则现在使用新值更新expected,并再次尝试代码。
https://stackoverflow.com/questions/66493926
复制相似问题