您是否应该将店铺障碍放入构造函数中?
这是一个例子。最初假设import sympy as sym
u = sym.symbols('u')
sym.plotting.plot(sym.sin(u), (u,-5,5))
。
一个线程A创建一个对象,分配给一个字段,并将其分配给一个全局变量:
global_f = f = r = 0
另一个线程B从全局变量中获取引用,然后读取该字段。
class Foo {
int x;
void Foo(int x) {
this.x = x;
}
}
f = new Foo(42);
global_f = f;
假设线程B从线程B读取对象引用的执行,它可以从r = global_f.x;
读取到X
的值是多少?总是42岁?
我对C ++ 和 Java的行为感兴趣。根据我对内存模型的理解,r
不能保证为42。
为确保正确初始化对象的字段,我们可以将store-store-barrier放在构造函数的末尾。这似乎是C ++和Java的一个陷阱。至少对于Java来说,最终字段的一切都很好,不是吗?这在实践中并不重要,因为至少在x86和AMD64上,商店商店屏障是NOP。但是,在ARM或POWER等其他架构上,它不是。
答案 0 :(得分:1)
在Java中,除非您将r
字段声明为42
,否则无法保证x
为final
。
为确保正确初始化对象的字段,我们可以将store-store-barrier放在构造函数的末尾。这似乎是C ++和Java的一个陷阱。
这是评论而不是问题。然而,相反的论点是,在所有构造函数的末尾加上一个隐含的障碍导致在各种情况下不必要的性能损失; e.g。
f
的多线程代码x
的访问受同步方法的保护。Java和C ++的内存模型是简单性和性能考虑之间的折衷。如果你走得太过简单(即设计出所谓的陷阱),多线程代码就不会给你那种人们想要/需要的加速。