3

我想对一个共享变量做两个操作。我需要保证它可以原子地完成。有人可以帮助我澄清以下方法是否正确:

#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 部分中使用 atomic 包。

4

1 回答 1

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_strongindex是将存储的值与进行比较的原子操作loc_index;如果它们相等,则存储desiredindex; 如果它们不相等,它将复制indexinto的值loc_index。这可以帮助您确保存储的下一个值index是正确的。

于 2013-02-27T18:57:12.110 回答