在复制构造函数中复制原子的非锁定方式

Nonlocking Way to Copy Atomics in Copy Constructor

我正在为需要将两个 std::atomic<T> 成员复制到新对象中的数据结构编写复制构造函数。虽然在我的用例中该过程不一定必须是原子的,但我更愿意尽可能拥有最正确的解决方案。

我知道 std::atomic<T> 明确删除了复制构造函数,以强制用户使用原子接口。

atomic(const atomic&) = delete;

我现在正在做的事情是这样的:

SomeObject(const SomeObject& other): 
   _atomic1(other._atomic1.load()),            
   _atomic2(other._atomic2.load()) {
...
}

我不相信这个操作是原子的,我也不知道有什么方法可以做到这一点(没有锁)。

有没有办法自动复制这些值(没有锁)?

唯一的方法是制作一个包含两个 T 的简单可复制结构 S 并使用 std::atomic<S>.

请注意,这仅在您从一开始就使用此 S 时才有效 - 无法在没有锁的情况下以原子方式加载两个单独的原子。

所以代替:

struct SomeObject {
    SomeObject(const SomeObject& other) : i(other.i.load()), j(other.j.load()) { }
    std::atomic<int> i, j;
};

这样做:

struct SomeObject {
    SomeObject(const SomeObject& other) : data(other.data.load()) { }
    struct Data { int i, j; };
    std::atomic<Data> data;
};

请注意,这可能(可能)仍然在内部使用锁。使用 is_lock_free 检查是否存在。