fetch_mult的这种原子实现是否正确?

and*_*ras 5 c++ thread-safety lock-free atomicity stdatomic

该站点介绍了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;         
}
Run Code Online (Sandbox Code Playgroud)

我在理解此功能时遇到麻烦。如果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;
  }
}
Run Code Online (Sandbox Code Playgroud)

Jam*_*one 5

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