This site解释了C++ 11原子,并给出了默认fetch_mult类型未提供的原子std::atomic<T>操作的示例实现:

#include <atomic>
#include <iostream>

template <typename T>
T fetch_mult(std::atomic<T>& shared, T mult){
  T oldValue= shared.load();
  // 1
  while (!shared.compare_exchange_strong(oldValue, oldValue * mult));
  return oldValue;
}

int main(){
   std::atomic<int> myInt{5};
   std::cout << myInt << std::endl;
   fetch_mult(myInt,5);
   std::cout << myInt << std::endl;
}

我在理解此功能时遇到麻烦。如果fetch_mult在点// 1处被另一个也调用fetch_mult的线程中断,则不会出现一个线程死锁,因为除非compare_exchange_strong或另一个线程将值重新设置为true,否则mult==1将永远不会返回oldValue吗?

例如(T1和T2是各自的线程):
  • T1:oldValue = 5;
  • T2:oldValue = 5;
  • T2:compare_exchange_strong成功将值设置为25
  • T1:compare_exchange_strong永远不会成功完成,因为它的oldValue仍然是5,除非其他人再次将该值设置为5

  • 我的理解正确吗?如果是这样,这是否是fetch_mult的正确实现?
    template <typename T>
    T fetch_mult(std::atomic<T>& shared, T mult){
      while (true) {
        T oldValue = shared.load();
        if (shared.compare_exchange_strong(oldValue, oldValue * mult))
          return oldValue;
      }
    }
    

    最佳答案

    如果比较失败,atomic::compare_exchange_*将当前值加载到“expected”参数中。在您的示例中,在步骤4中,T1将使compare-exchange失败,并将25加载到oldValue中,然后在下一次迭代中成功。

    09-25 20:41