我想对共享变量进行两次操作。我需要保证它可以原子方式完成。有人可以帮我澄清以下方法是否正确:
#include <atomic>
std::atomic<int> index;
void function()
{
// I need the variable index to be incremented but bound in the
// range of [0,9].
int loc_indx = index.load(std::memory_order_acquire);
index.store( (loc_indx+1)%10 , std::memory_order_release);
}
根据我的理解,索引存储操作和索引加载操作必须一起发生。这里的一些专家能否澄清上述代码是否等同于以下伪代码:
ATOMIC
{
index = (index+1)%10;
}
我一直在使用Visual Studio 2012的c ++部分中的原子包或/和1.53的boost :: atomic部分。
答案 0 :(得分:4)
与锁相比,原子的整个目的是提高性能。
您的代码中没有锁。 memory_order
枚举只是为了确保编译器不对代码重新排序(也不让CPU重新排序)。这意味着某些其他线程很可能会修改load
和store
之间的值。如果存储的值必须取决于先前的值,那么在两者之间完成的计算将被浪费,需要重做。这样做可以比锁更有效,因为并发修改实际发生的可能性很低,而且计算既便宜又简单。
知道之前的值时存储,否则重新计算并重试。类似的东西:
int loc_index = index.load(std::memory_order_acquire);
int desired = (loc_index+1)%10;
while ( !index.compare_exchange_strong( loc_index, desired ) )
{
desired = (loc_index+1)%10;
}
compare_exchange_strong
是原子操作,用于将index
中存储的值与loc_index
进行比较;如果它们相等,则将desired
存储到index
;如果它们不相等,则会将index
的值复制到loc_index
。这有助于您确保下一步
存储在index
中的值是正确的。