c++线程安全累加器

c++ Thread safe accumulator

本文关键字:累加器 安全 线程 c++      更新时间:2023-10-16

我需要根据分钟间隔监控内部流量,所以我决定做这样的事情:

Flow{
   void send();
   static uint accumulator;
}
//Only single thread call to send
void Flow::sendPacket(pck){
   accumulator+=pck.size();
   do();
}
//Only single thread call to monitor . **No the same thread that call to send!**
Monitor::monitor(){
   //Start monitor
   Flow::accumulator = 0;
   sleep(60);
   rate  = accumulator/60;
}

如果不使用原子,初始化为0的风险会不会正确发生

我担心的是,即使是原子也不能保证init,因为如果同时将init监控为0,同时用旧值进行累加,那么新的累加值将基于旧值而不是init值。

此外,我还关注原子弹的惩罚。对每个数据包调用send。

Volatile对多线程没有帮助。您需要防止同时更新accumulator的值,并在另一个线程读取该值的同时进行更新。如果您有C++11,您可以使accumulator原子化:std::atomic<uint> accumulator;否则,您需要围绕对其值的所有访问锁定互斥。

volatile对于在线程之间共享数据既不必要也不充分,所以不要使用它。

如果它可能被多个线程访问,那么您必须:

  • 使用C++11原子库或编译器特定的语言扩展(如果不可用)使访问成为原子访问,或者
  • 使用互斥锁或类似锁,使用C++11线程库或其他库(Boost.Thread、POSIX线程、Intel TBB、Windows API或许多其他库)保护它(如果不可用)

否则,您将有一个数据竞赛,给出未定义的行为。

如果只有一个线程可以访问它,那么您就不需要做任何特别的事情。