什么字段';根据Java内存模型,读线程可以看到部分初始化对象的s值吗?

什么字段';根据Java内存模型,读线程可以看到部分初始化对象的s值吗?,java,concurrency,jvm,java-memory-model,Java,Concurrency,Jvm,Java Memory Model,更具体地说,假设一个对象被部分初始化,并且一个字段x被该对象的构造函数初始化为null,那么读取该部分初始化对象的其他线程是否可能看到null以外的任何其他值 如果我理解正确,就不能保证Java内存模型本身的值在这种情况下总是空的。问题是:考虑到CPU缓存和JVM内存体系结构,是否应该合理地预期该值不能为null 默认情况下,引用成员变量初始化为null。如果构造函数将字段设置为非null值,那么其他线程可能会看到null或非null值。但是如果构造函数也将该值设置为null(在一个简单的场景中

更具体地说,假设一个对象被部分初始化,并且一个字段x被该对象的构造函数初始化为null,那么读取该部分初始化对象的其他线程是否可能看到null以外的任何其他值


如果我理解正确,就不能保证Java内存模型本身的值在这种情况下总是空的。问题是:考虑到CPU缓存和JVM内存体系结构,是否应该合理地预期该值不能为null

默认情况下,引用成员变量初始化为null。如果构造函数将字段设置为非null值,那么其他线程可能会看到null或非null值。但是如果构造函数也将该值设置为null(在一个简单的场景中这似乎是多余的),那么其他线程就不可能看到null以外的任何值(该字段唯一的值是null,因此不存在看到任何其他值的问题)

默认情况下,引用成员变量初始化为null。如果构造函数将字段设置为非null值,那么其他线程可能会看到null或非null值。但是如果构造函数也将该值设置为null(在一个简单的场景中这似乎是多余的),那么其他线程就不可能看到null以外的任何值(该字段唯一的值是null,因此不可能看到任何其他值)是的,这是可能的–不能保证一个线程在构造函数中初始化的对象会被另一个线程正确读取。Java内存模型允许编译器对构造函数中的语句重新排序,只要重新排序不会影响初始化完成时对象的状态

另一个线程可以在内存中分配对象之后,但在构造函数完成之前获取对该对象的引用,并且可以读取未初始化的值

您需要使用synchronized关键字或使用synchronized collections来保护对此类变量的访问


请参阅:

是这是可能的–不能保证一个线程在构造函数中初始化的对象会被另一个线程正确读取。Java内存模型允许编译器对构造函数中的语句重新排序,只要重新排序不会影响初始化完成时对象的状态

另一个线程可以在内存中分配对象之后,但在构造函数完成之前获取对该对象的引用,并且可以读取未初始化的值

您需要使用synchronized关键字或使用synchronized collections来保护对此类变量的访问


请参阅:

如果您遵守关于类设计的约定和建议(例如,不要在构造函数中调用可能被重写的方法,请使用Property同步/并发处理方法),这应该不会有任何问题。我知道。我只是想知道可能发生的最坏情况是什么——默认值还是任何随机值。如果您遵守关于类设计的约定和建议(例如,不要在构造函数中调用可能被重写的方法,请使用Property同步/并发处理方法),这应该不会有任何问题。我知道。我只是想知道最糟糕的情况是什么——默认值还是任何随机值。这是正确的。我想知道的是,“未初始化的值”是指始终为null(对于引用字段),还是任何值都可以是任意随机值?换句话说,如果我不初始化一个引用字段,而另一个线程读取部分初始化的对象,是否保证读线程看到null?@pzieba一旦调用构造函数,它就会消失为零/false/null,否则可能会得到一个损坏的引用并使JVM崩溃。这是正确的。我想知道的是,“未初始化的值”是指始终为null(对于引用字段),还是任何值都可以是任意随机值?换句话说,如果我不初始化一个引用字段,而另一个线程读取部分初始化的对象,那么是否可以保证读线程看到null?@pzieba一旦调用构造函数,它就会离开zero/false/null,否则可能会得到一个损坏的引用并使JVM崩溃。谢谢这个答案!还有一个问题:保证是来自JMM本身还是只是JMV特性?引用成员变量默认为null(甚至在构造函数运行之前)的事实在JLS中指定。JMM文档中的示例讨论了一些场景,在这些场景中,部分构造的对象中的字段似乎保存着它们的初始/默认值(null/0/false),而实际上构造函数为它们分配了不同的值。在任何情况下,线程都不能看到初始默认值null/0/false。例如,请参阅此处的第一个示例-感谢您的回答!还有一个问题:保证是来自JMM本身还是只是JMV特性?引用成员变量默认为null(甚至在构造函数运行之前)的事实在JLS中指定。JMM文档中的示例讨论了一些场景,在这些场景中,部分构造的对象中的字段似乎保存着它们的初始/默认值(null/0/false),而实际上构造函数为它们分配了不同的值。在任何情况下,线程都不能看到初始默认值null/0/false。例如,请参考此处的第一个示例-