Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 指针地址交换在C+;中总是一个原子操作吗+;?_C++_Windows_Multithreading - Fatal编程技术网

C++ 指针地址交换在C+;中总是一个原子操作吗+;?

C++ 指针地址交换在C+;中总是一个原子操作吗+;?,c++,windows,multithreading,C++,Windows,Multithreading,关于这个问题和提供的答案,我是否可以假设在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;

关于这个问题和提供的答案,我是否可以假设在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;
};

现在,使用<代码> Foo<代码>的线程通过一个实例,例如“代码> Bar < /C> >,以及其他线程调用<代码> BAR::BuffDoField()/<代码>

< P> <强> C++标准>P>

<强> NO>强>,同时修改/访问RAW2指针不能保证是C++中的原子操作。< /P>

C++标准称,如果一个线程修改内存位置,另一个修改/访问同一内存位置,则存在数据竞争,并且如果存在这样的数据竞争,程序将遭受未定义的行为。 [多线程简介]

4)
如果其中一个表达式修改内存位置(1.7),而另一个表达式访问或修改同一内存位置,则两个表达式求值会发生冲突

21)
如果一个程序在不同线程中包含两个冲突的操作,则该程序的执行包含一个数据竞争,其中至少一个操作不是原子操作,并且两个操作都不在另一个线程之前发生。任何这样的dat竞争都会导致未定义的行为

一,。raw未包装在
std::atomic
或同等文件中


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

在windows下,可以保证对正确对齐的
32位
变量的读/写始终是原子的,正如前面引用的链接所述

64位
窗口上,对正确对齐的
64位
变量的访问也是原子的

联锁变量访问-

对正确对齐的32位变量的简单读写是原子操作。换句话说,您不会只更新变量的一部分;所有位都以原子方式更新

但是,访问不保证同步。如果两个线程从同一个变量读写,则无法确定一个线程是否将在另一个线程执行写操作之前执行读操作


这是什么意思?

标准说明了一件事,而微软的文档说明了另一件事。。我们应该信任哪些人并与之合作?这当然取决于我们正在做什么

如果我们是为windows平台开发soley,我们可以了解所用编译器在代码生成方面的保证,然后从那里开始,但是如果我们想编写可以在不同平台下编译和运行的代码,唯一值得信任的是标准


在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
的实现时,我们很容易发现这些操作没有正确同步

在Windows下读/写一个32位变量是安全的,但在上面没有什么可以保证代码< > x>代码>和<代码> y>代码>当我们在<代码>掉期< /代码>的时候没有值<代码> 2 >代码>


但是,可以保证
x
永远不会包含前一个
x
中的50%字节和
y
中的50%字节,或类似内容。。个别写入是原子的。

设置
foo
可能是原子的,但它是特定于实现的。原因是大多数平台在一条指令中写入一个字大小的地址,这是一种原子操作。然而,您的平台并不要求将其指针存储在单词大小的位置,尽管很少不这样做

您还需要考虑指令重新排序以及其他线程可能在一段时间内看不到写入
foo
的情况。指针的位置可能保存在处理器缓存中,而不是刷新到内存中


考虑到所有这些,您最好使用
std::atomic
类型,或者如果您没有访问C++11的权限,那么应该有某种互锁的读/写函数可用。

交换通常不是原子的。它必须读取两个值,然后写入两个值。(因此,当交换
a
b
时,
a
b
的旧值结束,
b
a
的旧值结束)jalf认为交换通常不是原子的,这是正确的,但Windows确实提供了如下方法:,作为执行交换的一种方式。请注意,您没有交换,而是在分配。还要注意,指针可能是64位。@Jarod42:我确实没有交换。谢谢。实际上微软的文档也这么说:虽然读/写可能是原子的(实际上应该参考处理器的英特尔规范),但交换(涉及多个原子)肯定不是。