java - 最终字段与。易挥发的
问题描述
从最终语义的java
文档中:field
他们保证看到final
设置的字段constructor
,请在下面找到代码:
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}
static void reader() {
if (f != null) {
int i = f.x; // guaranteed to see 3
int j = f.y; // could see 0
}
}
}
现在在这里我对volatile
vs感到困惑final
。
据我了解final
,使用文件确保您不能更改应用程序中的变量,并volatile
保证保持顺序并避免发生在关系之前。
所以我的问题是他们如何保证可见性和使用final
变量而不是排序volatile
?请帮忙。
解决方案
所以我的问题是他们如何使用最终变量来保证可见性和排序
因为他们是这样定义的,而现在虚拟机的工作就是遵守这个定义。
当然,接下来的问题是:他们为什么要这样定义?
这是因为 Java 内存模型的一个奇怪的“特性”。考虑这个例子
class Foo {
int x;
volatile int y;
Foo() {
x = 3;
y = 4;
}
static final Foo INSTANCE;
static {
INSTANCE= new Foo();
}
}
静态初始化器将被编译成这个(简化伪代码):
Foo tmp = allocate(Foo.class)
Foo.INSTANCE = tmp
tmp.x = 3
tmp.y = 4
如您所见,实例在构造函数执行之前是公开的,volatile
这里没有任何改变。
对于大多数开发人员来说,这种行为是出乎意料的,并且可能导致非常难以调试的错误。因此,为了稍微减少这个问题的范围,规范被调整为要求在实例公开之前初始化最终字段。
上面的示例,带有x
声明final
的 .
Foo tmp = allocate(Foo.class)
tmp.x = 3
Foo.INSTANCE = tmp
tmp.y = 4
推荐阅读
- linux - 将代码写入输出文件的更快方法
- c# - 更改 UI 图像的精灵,保留纵横比被选中但不起作用?统一2019.1.0f2
- javascript - 解决重大错误后插件(floatThead.js)不再工作
- spring - 带有安全表达式的 @Query 上的类型期望不匹配
- typescript - 我是否需要在 TypeScript 的类和接口中注释对象属性?
- java - 带有 Apache Camel 的 Spring Boot 应用程序在启动后立即关闭
- dialog - UIPath如何自动设置用户名和密码?
- javascript - 我想打破循环
- hadoop - 如何使用 HBase 二级索引表作为 MapReduce 作业的输入?
- django - Django 不提供常见的静态文件