2017-06-13 104 views
1

您是否应该将商店门槛放入构造函数中?构造函数是否有StoreStore障碍?

下面是一个例子。首先假设global_f = f = r = 0。 一个线程A创建一个对象,分配给一个字段,并将其分配给一个全局变量:

class Foo { 
    int x; 
    void Foo(int x) { 
     this.x = x; 
    } 
} 

f = new Foo(42); 
global_f = f; 

另一个线程B获取从全局变量的参考,然后读取该字段。

r = global_f.x; 

假设处决其中线程B读取从线程B的对象的引用,什么值可以从Xr读?总是42还是不是?

我对C++ Java的行为很感兴趣。对我的内存模型的了解,r不保证是42.

为了确保对象的字段被正确初始化,我们可以在构造函数的末尾放置store-store-barrier。这似乎是在C++和Java中的一个陷阱。至少对Java而言,最终领域的一切都很好,不是吗?这在实践中并不那么重要,因为至少在x86和AMD64上,存储障碍是NOP。但是,在其他体系结构(如ARM或POWER)中则不然。

+1

仅限于C++:内存屏障不是(不应该)自动添加的,它们是程序员的问题。以下指导原则适用于:“对您使用规则的唯一支付”_和多线程对于编译器的静态分析来说过于复杂(编译器会分别查看每个编译单元)。 –

+0

您需要缩小要查询的语言的范围。 Java和C++有不同的内存模型和语言语义。首先,类是C++中的值,而不是引用。另一个是Java的'volatile'与C++有很大的不同 –

+0

我不明白为什么应该在这里单独列出构造函数。这种情况与设置'x'的任何其他方法调用没有什么不同。 – EJP

回答

1

在Java中,没有保证r42除非你声明x字段final


为了确保对象的字段被正确初始化,我们可以把店里店,障碍在一般的构造函数的结束。这似乎是在C++和Java中的一个陷阱。

这是一条评论,而不是一个问题。然而,相反的观点是,在所有构造函数的最后加上一个隐含的障碍会导致在各种情况下不必要的性能下降;例如

  • 为单线程代码,
  • 多线程代码,其中f没有为多线程代码那里获得x由一个同步方法把守出版

Java和C++的内存模型是简单性和性能考虑之间的折衷。如果你过于简单(即通过设计出所谓的陷阱),多线程代码不会为你提供人们想要/需要的加速。

相关问题