构造函数是否应该具有应用商店屏障?
Should constructors have a StoreStore barrier?
你应该把store-store-barrier放到构造函数中吗?
下面是一个示例。最初假设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 读取对象引用的执行,它可以从X
读取到r
的什么值?总是42岁与否?
我对C++和Java的行为很感兴趣。据我对记忆模型的理解,r
不能保证是42。
为了确保对象的字段正确初始化,我们通常可以将存储-存储-屏障放在构造函数的末尾。这似乎是C++和Java的一个陷阱。至少对于Java来说,最终字段一切都很好,不是吗?这在实践中并不那么重要,因为至少在x86和AMD64上,商店-商店-屏障是NOP。但是,在ARM或POWER等其他架构上则不然。
在 Java 中,除非您将x
字段声明为final
,否则无法保证r
将被42
。
为了确保对象的字段正确初始化,我们通常可以将存储-存储-屏障放在构造函数的末尾。这似乎是C++和Java的一个陷阱。
这是一个评论,而不是一个问题。 然而,相反的论点是,在所有构造函数的末尾放置隐式障碍会导致在各种情况下不必要的性能下降;例如
- 对于单线程代码,
- 对于未发布
f
的多线程代码 - 对于由同步方法保护对
x
的访问的多线程代码。
Java 和 C++ 的内存模型是简单性和性能考虑之间的折衷。 如果你过于追求简单(即通过设计所谓的陷阱),多线程代码将无法给你人们想要/需要的那种加速。
相关文章:
- 码头化的C++应用程序是否向后兼容早期的内核版本
- 是否可以编译 Gtk+ 应用程序以同时在 Gtk 2 和 3 上运行
- 如何使用C++确定应用程序是否已在窗口中启动?
- 是否可以从控制台应用程序使用 C++/WinRT 创建窗口?
- 如何查询以确定我的 MacOS/X 应用程序是否处于应用程序午睡模式?
- 是否有可能构建面向Linux和Windows的.Net Core C++ / CLI应用程序?
- 从头开始为应用程序创建 docker 映像是否有意义?
- 是否可以将键盘输入绑定到 Win32 中的单个应用程序?
- 确定C++应用程序是否作为具有旧版支持的 UWP 应用运行
- 是否可以将不同的编译器嵌入到我的应用程序中?
- Windows 和 Android 应用程序是否需要 SSL?
- GCP 或 AWS 是否支持 C++ 和 GUI 应用程序开发?
- 使用全局 IP 地址时,C++ winsock 2 应用程序中的代码是否必须更改?
- 根据应用程序是否已自动化显示不同的 QML 文件
- 是否可以在 Azure 应用服务中安装 C++ 编译器
- 如何检查应用程序是否安装了 jni?
- 是否可以在QT GUI应用程序中处理事件时播放加载动画指示器?
- 是否可以将 VBA 编程环境添加到我的C++应用程序?
- 在通过标准::ref(值)时,是否应该应用标准::可选?
- 基于内核版本 X.XX 构建的 C++ Linux 应用是否会在早期版本上运行