Java 非最终字段的安全初始化

Java 非最终字段的安全初始化,java,concurrency,initialization,Java,Concurrency,Initialization,从 新的JMM还寻求提供初始化安全性的新保证——只要一个对象被正确构造,这意味着在构造函数完成之前没有发布对该对象的引用,那么所有线程都将看到其构造函数中设置的最终字段的值,无论是否使用同步将引用从一个线程传递到另一个线程 那么在构造函数中初始化的非最终字段是什么呢?根据对对象的引用在构造函数完成之前没有发布,我可以得出结论,行为与final字段相同。正确吗?上这个简单的课: class Example { final int i; int j; Example() {

新的JMM还寻求提供初始化安全性的新保证——只要一个对象被正确构造,这意味着在构造函数完成之前没有发布对该对象的引用,那么所有线程都将看到其构造函数中设置的最终字段的值,无论是否使用同步将引用从一个线程传递到另一个线程


那么在构造函数中初始化的非最终字段是什么呢?根据对对象的引用在构造函数完成之前没有发布,我可以得出结论,行为与final字段相同。正确吗?

上这个简单的课:

class Example {
    final int i;
    int j;
    Example() { i = 5; j = 5; }
}
在构造过程中不会发布对对象的引用,因此JMM保证访问新创建的示例实例的所有读取线程都会看到i=5。无论实例是如何发布的,情况都是如此

但是,如果实例未安全发布,这些线程可能会看到j=0,即默认值。安全出版物习惯用法包括:

从静态初始化器初始化实例 将对实例的引用标记为volatile 将对实例的引用标记为最终引用 同步所有访问
以这个简单的课程为例:

class Example {
    final int i;
    int j;
    Example() { i = 5; j = 5; }
}
在构造过程中不会发布对对象的引用,因此JMM保证访问新创建的示例实例的所有读取线程都会看到i=5。无论实例是如何发布的,情况都是如此

但是,如果实例未安全发布,这些线程可能会看到j=0,即默认值。安全出版物习惯用法包括:

从静态初始化器初始化实例 将对实例的引用标记为volatile 将对实例的引用标记为最终引用 同步所有访问 对于易失性变量,所有线程都可以立即看到写操作。无论写入是否在构造函数中完成,都是这种情况

对于非易失性变量,写入可能不会立即对其他线程可见。无论写入是否在构造函数中完成,都是这种情况

一个特例是final字段。一旦构造函数完成,对对象最终字段的写入保证对所有线程可见

你可以读更多

对于易失性变量,所有线程都可以立即看到写操作。无论写入是否在构造函数中完成,都是这种情况

对于非易失性变量,写入可能不会立即对其他线程可见。无论写入是否在构造函数中完成,都是这种情况

一个特例是final字段。一旦构造函数完成,对对象最终字段的写入保证对所有线程可见


您可以阅读更多内容。

如果示例中也包含可变变量c,该怎么办?这个变量初始化的行为如何?@michaelnesterenko在构造函数中为c设置的值可以从其他线程看到。您也可以使用它来安全地发布j,但这很容易出错。若示例中也有易失性变量c呢?这个变量初始化的行为如何?@michaelnesterenko在构造函数中为c设置的值可以从其他线程看到。您也可以使用它安全地发布j,但这很容易出错。