指针地址交换总是在C ++中的primefaces操作?

关于这个问题有没有32位variables不能正确alignment和提供的答案的情况下,我可以假设我可以交换地址,没有任何副作用,当在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的实例,以及调用Bar::buildFoo()其他线程的后果是什么?

C ++标准

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

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

[ intro.multithread ]

4) 如果其中一个表达式评估修改一个内存位置(1.7),而另一个访问或修改相同的内存位置,那么两个表达式的评估冲突

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

1. raw不是被包装在std::atomic<Foo*> ,或者是等价的。


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

在windows下,保证正确对齐的 32-bit变量的读/写总是原子的 ,正如前面提到的问题/答案链接的文章所述。

访问正确对齐的64-bit变量在64-bit窗口中也是原子性的。

互锁变量访问http://msdn.microsoft.com/en-us/library/ms684122%28VS.85%29.aspx

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

读取/写入一个32位的变量在windows下是安全的,但是在上面没有任何东西可以保证在我们swap时候xy的值都不是2

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

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

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

考虑到这一切,你最好使用std::atomic类型,或者如果你没有访问C ++ 11,那么应该有某种互锁的读/写功能可用。