原子读取然后用 std::atomic 写入

Posted

技术标签:

【中文标题】原子读取然后用 std::atomic 写入【英文标题】:atomic read then write with std::atomic 【发布时间】:2017-08-24 10:39:06 【问题描述】:

假设以下代码

#include <iostream>
#include <atomic>
#include <chrono>
#include <thread>

std::atomic<uint> val;

void F()

   while(true)
   
      ++val;
   


void G()

   while(true)
   
      ++val;
   


void H()

   while(true)
   
      std::this_thread::sleep_for(std::chrono::seconds(1));
      std::cout <<"val="<< val << std::endl;
      val = 0;
   


int main()

   std::thread ft(F);
   std::thread gt(G);
   std::thread ht(H);
   ft.join();
   gt.join();
   ht.join();

   return 0;

基本上是两个线程递增val 的值,第三个线程每秒报告这个值然后重置它。问题是,当第三个线程读取该值然后将其设置为零时,可能会丢失增量(我们没有将它们包含在报告中)。所以我们需要一个原子的读写机制。有没有一种我不知道的干净方法来做到这一点? PS:我不想锁定任何东西

【问题讨论】:

或许std::atomic::exchange 【参考方案1】:

std::atomic::exchange 方法似乎是您所追求的(强调我的):

以原子方式将基础值替换为期望值。操作是read-modify-write操作。


如下使用:

auto localValue = val.exchange(0);
std::cout << "Value = " << localValue << std::endl;

【讨论】:

【参考方案2】:

正如其他人提到的那样,std::atomic::exchange 会起作用。

在两行执行之间提及为什么您当前的代码执行您所说的:

std::cout <<"val="<< val << std::endl;
val = 0;

其他两个线程有​​时间递增ht线程即将重置的值。

std::atomic::exchange 将在一个“原子”操作中完成这些行。

【讨论】:

以上是关于原子读取然后用 std::atomic 写入的主要内容,如果未能解决你的问题,请参考以下文章

第31课 std::atomic原子变量

用 std::atomic 实现的 shared_lock

std::atomic_ref 如何为非原子类型实现?

C++ 原子操作 std::atomic<int>

是否可以使用 std::atomic 使类原子的复杂成员函数?

将 std::atomic_flag 包装在 getter/setter 中会使其“原子性”无效吗?