首页 >后端开发 >C++ >如何仅使用 32 位原子实现 64 位原子计数器?

如何仅使用 32 位原子实现 64 位原子计数器?

Barbara Streisand
Barbara Streisand原创
2025-01-04 16:52:39590浏览

How to Implement a 64-Bit Atomic Counter Using Only 32-Bit Atomics?

使用 32 位原子实现 64 位原子计数器

简介:

本文介绍了 64 位原子计数器的设计和实现,使用32 位原子操作。它旨在提供对共享计数器的高效、无锁访问,特别适合具有多个读取器和单个写入器的场景。

设计注意事项:

建议的设计基于“SeqLock”的概念,它利用 32 位生成计数,其中低位用作读锁

代码实现:

class counter {
    atomic<uint32_t> lo_;
    atomic<uint32_t> hi_;
    atomic<uint32_t> gen_;

    uint64_t read() const {
        auto acquire = memory_order_acquire;
        uint32_t lo, hi, gen1, gen2;
        do {
            gen1 = gen_.load(acquire);
            lo = lo_.load(acquire);
            hi = hi_.load(acquire);
            gen2 = gen_.load(acquire);
        } while (gen1 != gen2 || (gen1 & 1));
        return (uint64_t(hi) << 32) | lo;
    }

    void increment() {
        auto release = memory_order_release;
        gen_.fetch_add(1, release);
        uint32_t newlo = 1 + lo_.fetch_add(1, release);
        if (newlo == 0) {
            hi_.fetch_add(1, release);
        }
        gen_.fetch_add(1, release);
    }
};

设计评估:

  1. 正确性: 该设计提供了 64 位原子计数器的有效实现,防止竞争条件并确保所有线程都看到一致的值。
  2. 效率:使用 32 位原子而不是 64 位原子可以提高性能,特别是在 64 位原子操作成本高昂的系统中。
  3. 无锁性:SeqLock设计消除了对锁的需求,从而实现高并发访问

替代解决方案:

需要注意的是,原子读-修改-写(RMW)操作对于增量操作。相反,更有效的方法是使用带有释放内存排序的纯加载和存储:

void increment() {
    auto release = memory_order_release;
    uint64_t count = lo_.load(release) | (uint64_t(hi_.load(release)) << 32);
    count++;
    lo_.store(count & uint32_t(-1), release);
    hi_.store((count >> 32) & uint32_t(-1), release);
}

结论:

建议的实现提供了一个高效且正确的解决方案用于使用 32 位原子创建 64 位原子计数器。 SeqLock 设计确保计数器在无锁的情况下运行,同时允许多个读取器和单个写入器同时操作,而不会引入数据竞争。

以上是如何仅使用 32 位原子实现 64 位原子计数器?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn