Long Atomic Int的实现

时间:2013-03-19 10:46:15

标签: c++ multithreading counter atomic

我想使用原子计数器(多线程计算),计数通常为2 ^ 40,所以我不能直接使用32位int原子计数器。我还没有c ++ 11(我将迁移到它但还没有,因为这对我来说有成本)我必须在32位和64位平台上编译。 我目前使用QT,所以我可以使用QAtomicInt。

以下是我的想法:

(initialization...)
QAtomicInt counterLo = 0;
QAtomicInt counterHi = 0;


void increment()
{
    int before = counterLo.fetchAndAddOrdered(1);
    if(before==INT_MAX)
    {
        counterHi.fetchAndAddOrdered(1); //Increment high word
        counterLo.fetchAndAddOrdered(INT_MAX);    //Increments low word to -1
        counterLo.fetchAndAddOrdered(1);   //Increments low word to 0
    }         
}

uint64_t value()
{
    //Wait until the low word is non-negative
    int lo = counterLow;
    while(lo<0)
        lo = counterLow;

    return (uint64_t)counterHi * ((uint64_t)INT_MAX+1) + (uint64_t)lo;
}

这是对的吗?我已经尝试用互斥锁制作计数器,但我的性能下降了大约10%。这被称为每秒约1百万次,在8个线程之间共享(蒙特卡罗模拟的样本计数器)

谢谢!

2 个答案:

答案 0 :(得分:1)

这不是整体原子,请参阅以下示例:

  • hi=0,lo=INT_MAX
  • T1调用value(),获取lo=INT_MAX,中断
  • T2调用increment()增加hi至1
  • T1恢复并读取counterHi,获取1,返回值2 ^ 32 + INT_MAX

这可能不是你想要的。难道你不能只是分割你的样本空间,让每个线程计算n / 8项而不争夺锁定?

答案 1 :(得分:1)

当然这不是原子的。原子操作的顺序可以被中断。我建议使用保护(互斥或关键部分)。