如何在 C++ 中为共享计数器实现简单的比较和交换

Posted

技术标签:

【中文标题】如何在 C++ 中为共享计数器实现简单的比较和交换【英文标题】:how to implement simple Compare And Swap in C++ for shared counter 【发布时间】:2018-02-15 07:46:56 【问题描述】:

我正在尝试学习没有锁的并发性。因此,我试图为共享变量计数器实现简单的比较和交换(cas)。我尝试创建 10 个线程,并希望使用 CAS 将每个线程的计数器值增加 1。因为 CAS 存储旧值并与当前值进行比较,并且仅在值未更改时才更新。寻找[这里] 我尝试实现 CAS,但无法正确执行。 c++中如何实现计数器共享变量的CAS?

#include <iostream>
#include <thread>
#include <unistd.h>
#include <atomic>



std::atomic<int> count = 0;
std::mutex n_mutux;

void increase_counter(int i)

    int old_value = count.load() ;
    while (!count.compare_exchange_weak(old_value, old_value +1))
    
    




int main() 

    int thread_num =10;
    std::thread t[thread_num];
    for(int i=0;i<thread_num;i++)
    
        t[i]=std::thread((increase_counter),i);
    

    for(int i=0;i<thread_num;i++)
    
        t[i].join();
    
   std::cout<<count;

【问题讨论】:

你应该在你的 while 循环中更新 old_value std::thread((increase_counter), i) 中的括号是干什么用的? @FlorianM。我正在尝试使用 oldvalue +1 进行更新。计数初始化为原子共享变量是否正确?? @DeanSeo increase_counter 是每个线程使用 i 调用的函数,以防需要线程 ID。 代码似乎是正确的。什么是问题?您是否从std::cout&lt;&lt;count; 得到意外输出?还是什么? 【参考方案1】:

你的解决方案是正确的。

另一种方法是使用增量,请参阅std::atomic::operator++()fetch_add(1, std::memory_order_acq_rel)。这两个不需要繁忙的等待循环。

std::atomic&lt;int&gt; count = 0 的初始化存在编译器错误。修复:

std::atomic<int> count0;

更高效的 CAS 是:

void increase_counter(int i) 
    int old_value = count.load() ;
    while(!count.compare_exchange_weak(old_value, old_value + 1,
                                       std::memory_order_release,
                                       std::memory_order_relaxed)) 
        _mm_pause();

Pause Intrinsic:

pause 内在函数用于自旋等待循环,处理器实现动态执行(尤其是乱序执行)。在自旋等待循环中,pause 内在函数提高了代码检测锁释放的速度,并提供了特别显着的性能增益。

下一条指令的执行会延迟一段特定于实现的时间。 pause 指令不会修改架构状态。对于动态调度,pause 指令减少了退出自旋循环的惩罚。

有关更多详细信息和基准,请参阅Benefitting Power and Performance Sleep Loops。

【讨论】:

以上是关于如何在 C++ 中为共享计数器实现简单的比较和交换的主要内容,如果未能解决你的问题,请参考以下文章

比较和交换如何用于任何共享数据结构的无等待互斥?

如何在 Linux 上的 C++ 程序中使用共享库(在本例中为 JsonCpp)?

c++ boost进程间交换(复制)非共享和共享字符串向量

C++ String的引用计数写时复制 的实现 《More Effective C++》

C++ String的引用计数写时复制 的实现 《More Effective C++》

计数排序算法是如何计数的?