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