c++ - 指针地址交换总是 C++ 中的原子操作吗?

标签 c++ windows multithreading

关于这个问题Is there cases where a 32-bit variable could not been properly-aligned以及提供的答案,我可以假设我可以在 Windows 平台下工作时交换地址而没有任何副作用吗?

例如:

struct Foo
{
    // whatever Foo can hold
};

struct Bar
{
    void buildFoo()
    {
        auto tmp = new Foo;

        // do some stuff on tmp, or not

        foo = tmp;
    }

    Foo* foo;
};

现在,让一些线程通过 Bar 的实例使用 foo,而其他线程调用 Bar::buildFoo()?

最佳答案

C++ 标准

,不能保证同时修改/访问原始2 指针是c++ 中的原子操作。

C++ 标准规定,如果一个线程修改内存位置而另一个线程修改/访问相同的内存位置,则存在数据竞争,如果存在这样的数据竞争,则程序会出现未定义的行为.

[intro.multithread]

4) Two expressions evaluations conflict if one of them modifies a memory location (1.7) and the other one accesses or modifies the same memory location.

...

21) The execution of a program contains a data race if it contains two conflicting actions in different threads, at least one of which is not atomic, and neither happens before the other. Any such dat race results in undefined behavior.

1. raw 未被包裹在 std::atomic<Foo*> 中,或等效物。


实现特定行为(windows 32/64 位)

在 Windows 下,保证读/写正确对齐 32-bit正如 the article 所述,变量总是原子的question/answer 链接你之前提到过。

访问正确对齐的 64-bit变量在 64-bit 上也是原子的 window 。

Interlocked Variable Access - http://msdn.microsoft.com/en-us/library/ms684122%28VS.85%29.aspx

Simple reads and writes to properly-aligned 32-bit variables are atomic operations. In other words, you will not end up with only one portion of the variable updated; all bits are updated in an atomic fashion.

However, access is not guaranteed to be synchronized. If two threads are reading and writing from the same variable, you cannot determine if one thread will perform its read operation before the other performs its write operation.


这是什么意思?

标准说的是一回事,而 Microsoft 的文档说的是另一回事。我们应该信任和合作哪些?这当然取决于我们在做什么。

如果我们只为 windows 平台开发,我们可以阅读所用编译器在代码生成方面的保证,然后从那里开始,但是如果我们想编写可以在不同平台下编译和运行的代码,唯一的方法就是正确信任的东西是标准。


所以在 Windows 下工作时我可以安全地交换 32 位变量?

如果您所说的“交换” 是指如下代码片段中所写的操作,则答案是,但如果您的意思是“分配" 答案是

void swap (int& a, int& b) {
  int tmp = a;
  
  a = b;
  b = tmp;
}

int main () {
  int x = 1;
  int y = 2;

  swap (x, y);
}

上面的代码片段(或前面提到的文档)中没有任何内容表明这将是一个原子操作,并且在查看我们的 swap 的实现时我们很容易看到操作没有正确同步。

读/写单个 32 位变量在 Windows 下是安全的,但在上面没有任何东西可以保证 xy没有值 2当我们在 swap 的中间时.

但是,保证x never 将包含前一个 x 中 50% 的字节和 y 中 50% 的字节,或类似的.. 个人写入是原子的。

关于c++ - 指针地址交换总是 C++ 中的原子操作吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22038298/

相关文章:

c# - 在 C++ 和 C# 中使用 try/catch 的正确方法是什么?

windows - Base64 编码 "string"- Windows 命令行?

windows - git,Windows 上的 SSH_ASKPASS

c++ - 如何在 Visual Studio 2017 中为 Linux 应用程序启用多线程

c++ - 如何使用 C++ 使用字符串打印变量

c++ - C++ 中的性能损失

c++ - Qt 多 webview 单插槽处理

windows - 找不到 Docker entrypoint.sh

java - 在 Map Reduce 作业中使用多线程

c++ - 使用 pthread_create 时出现 "Segmentation fault (core dumped)"