两个std :: atomic可以成为一个联盟的一部分吗?

alk*_*edr 9 c++ atomic c++11

我想做这个:

union {
    std::atomic<uint128_t> u128;
    struct {
        std::atomic<uint64_t> u64_1;
        std::atomic<uint64_t> u64_2;
    };
};
Run Code Online (Sandbox Code Playgroud)

几个线程将读取和写入联合的两个部分.

安全吗?

编辑:我使用Linux,x86_64,clang 3.3

Edit2:我希望能够递增和递减u64_1,读取u64_2,并写入u128(compare_exchange)

Edit3:如果我使用原子内置函数怎么办?工会将如下所示:

union {
    uint128_t u128;
    struct {
        uint64_t u64_1;
        uint64_t u64_2;
    };
};
Run Code Online (Sandbox Code Playgroud)

u64_1将映射到u128的上半部分,u64_2将映射到下半部分.

Dav*_*eas 7

std::atomic<T>操作可以是无锁或锁定,这取决于是否架构提供了基本保证.你可以通过检查来检查std::atomic<T>::is_lock_free().

如果类型不是锁定的,则库可能通过计数器支持它.这反过来可能意味着该类型不再是下面的POD,这反过来意味着当从一个活动成员切换到另一个活动成员时,您有责任调用构造函数/析构函数.

如果存在128位但不是64位类型的互斥锁,则可能最终会出现值的布局重合的情况,但操作的原子性通过不同的方式得到保证,因此它似乎可以工作,但是失败虚假地,以一种难以察觉的方式.

  • §29.5/ 5说"原子整数专业化和专业化`atomic <bool>`应该有标准的布局.它们每个都有一个普通的默认构造函数和一个普通的析构函数.它们都应该支持聚合初始化语法." 因此,切换活动的union成员不需要构造函数/析构函数调用. (2认同)
  • @alkedr:如果没有锁定,几乎可以保证不安全,但如果它是无锁的,我仍然会查看硬件提供的内容以及库实现的功能.`uint128_t`不是标准类型,并且没有那么多具有128位寄存器的平台,所以如果可以保证我会感到惊讶.它还取决于您正在进行的操作,是否只是读/写或者您正在使用任何其他功能(原子增量或减量方式......).即使没有锁,我也不敢说它是安全的 (2认同)