最终领域与。易挥发的
Final fields Vs. Volatile
来自最终 field
语义的 java
文档:
他们保证看到 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
和 final
感到困惑。
据我了解,final
filed 用于确保您不能更改应用程序中的变量,volatile
保证保持顺序并避免发生关系之前发生。
所以我的问题是他们如何使用 final
变量而不是 volatile
来保证可见性和排序?请帮忙
So my question is how come they guarantee the visibility and ordering using final variable
因为他们是这样定义的,现在 VM 的工作就是遵守这个定义。
当然,后续的问题是:为什么要这样定义?
这是因为 Java 内存模型的一个奇怪的 "feature"。考虑这个例子
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
如您所见,实例是在执行构造函数之前 public 创建的,volatile
这里没有任何改变。
对于大多数开发人员来说,这种行为是出乎意料的,并且可能导致非常难以调试的错误。因此,为了稍微减少这个问题的扩展,规范被调整为要求在创建实例之前初始化最终字段 public.
以上示例,x
声明为 final
。
Foo tmp = allocate(Foo.class)
tmp.x = 3
Foo.INSTANCE = tmp
tmp.y = 4
来自最终 field
语义的 java
文档:
他们保证看到 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
和 final
感到困惑。
据我了解,final
filed 用于确保您不能更改应用程序中的变量,volatile
保证保持顺序并避免发生关系之前发生。
所以我的问题是他们如何使用 final
变量而不是 volatile
来保证可见性和排序?请帮忙
So my question is how come they guarantee the visibility and ordering using final variable
因为他们是这样定义的,现在 VM 的工作就是遵守这个定义。
当然,后续的问题是:为什么要这样定义?
这是因为 Java 内存模型的一个奇怪的 "feature"。考虑这个例子
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
如您所见,实例是在执行构造函数之前 public 创建的,volatile
这里没有任何改变。
对于大多数开发人员来说,这种行为是出乎意料的,并且可能导致非常难以调试的错误。因此,为了稍微减少这个问题的扩展,规范被调整为要求在创建实例之前初始化最终字段 public.
以上示例,x
声明为 final
。
Foo tmp = allocate(Foo.class)
tmp.x = 3
Foo.INSTANCE = tmp
tmp.y = 4