我正在实现一个非常轻巧的原子包装程序,作为针对Windows C++中原始数据类型的学习练习,并且我对实现赋值运算符有一些简单的问题。考虑下面的两个实现:

// Simple assignment
Atomic& Atomic::operator=(const Atomic& other)
{
    mValue = other.mValue;
    return *this;
}

// Interlocked assignment
Atomic& Atomic::operator=(const Atomic& other)
{
    _InterlockedExchange(&mValue, other.mValue);
    return *this;
}

假定mValue是正确的类型,并且 Atomic 类具有它作为成员。
  • 线程安全的赋值运算符是否需要_InterlockedExchange,还是简单的实现足以保证线程安全?
  • 如果简单的分配是线程安全的,那么是否甚至需要实现此类的分配运算符?编译器默认值就足够了,不是吗?
  • 如果简单分配在Windows中是线程安全的,那么在其他平台上它也是线程安全的吗?是否需要等效_InterlockedExchange来保证其他平台上的线程安全?
  • 最佳答案

    如果mValue是原始类型(在32位CPU上最多32位宽,在64位CPU上最多64位宽),并且您在x86 CPU上运行(在32或64位模式下)并且您无需手动将数据对齐,那么可以保证内存读写是原子的。

    这本身并不意味着编译器不会对内存访问进行重新排序,甚至不会完全优化内存访问,但是CPU会确保任何与这些大小的数据良好对齐的读写操作都是原子的。

    但是,请注意,我说的是原子性,而不是线程安全性,因为“线程安全性”取决于使用代码的上下文。

    10-01 20:05
    查看更多