Java 部分构造对象

Java 部分构造对象,java,Java,如果一个对象在初始化过程中对其他线程可见(在初始化过程中可见,但尚未完成),那么这是否可能?如果是的话,你能举一个简单的例子来证明你的理由吗 这可以通过多种方式实现 将对象传递给构造函数中的另一个线程,例如,在构造函数中启动一个线程 您将对象传递给另一个线程,但另一个线程会看到旧的、未初始化的值,因为这些字段不是final或volatile,也不是在锁定或同步的块中访问的。其他字段不保证线程安全 这可以通过多种方式实现 将对象传递给构造函数中的另一个线程,例如,在构造函数中启动一个线程 您将

如果一个对象在初始化过程中对其他线程可见(在初始化过程中可见,但尚未完成),那么这是否可能?如果是的话,你能举一个简单的例子来证明你的理由吗

这可以通过多种方式实现

  • 将对象传递给构造函数中的另一个线程,例如,在构造函数中启动一个线程
  • 您将对象传递给另一个线程,但另一个线程会看到旧的、未初始化的值,因为这些字段不是final或volatile,也不是在锁定或同步的块中访问的。其他字段不保证线程安全

    • 这可以通过多种方式实现

      • 将对象传递给构造函数中的另一个线程,例如,在构造函数中启动一个线程
      • 您将对象传递给另一个线程,但另一个线程会看到旧的、未初始化的值,因为这些字段不是final或volatile,也不是在锁定或同步的块中访问的。其他字段不保证线程安全

      最好的例子是众所周知的破坏双重检查锁定习惯用法。我将仅从中摘录与此论点相关的部分。以这个代码为例:

      public class Holder { public static File f; }
      

      在线程A的某个地方,您可以
      Holder.f=新文件(“路径”)和线程B中的其他地方,您可以
      文件xxf=Holder.f
      并继续使用它。即使您阅读了对
      Holder.f
      的引用,也不能保证
      文件
      实例的任何字段都将处于任何已定义状态。您可以读取所有的空值(零、假值,具体取决于类型),甚至可以读取非空值和空值的任意错误组合。

      最好的例子是众所周知的破坏双重检查锁定习惯用法。我将仅从中摘录与此论点相关的部分。以这个代码为例:

      public class Holder { public static File f; }
      

      在线程A的某个地方,您可以
      Holder.f=新文件(“路径”)和线程B中的其他地方,您可以
      文件xxf=Holder.f
      并继续使用它。即使您阅读了对
      Holder.f
      的引用,也不能保证
      文件
      实例的任何字段都将处于任何已定义状态。您可以读取所有空值(零、假值,具体取决于类型),甚至可以读取非空值和空值的任何错误组合。

      我猜它是Hi的重复,我猜它是Hi的重复!谢谢你的回答。我对volatile变量有疑问,比如:volatile Pool=newpool();如果池构造函数在初始化过程中抛出异常,则池指向何处,如果池构造函数抛出异常,池引用将保持不变——它不会引用部分构造的对象。@ ysavIT是否意味着它仍然指向先前分配的实例?是的,确切地,还是空的,如果引用以前为空。如果您将
      this
      传递到构造函数中的某个位置并引发异常,则将有一个部分构造的对象。;)你好谢谢你的回答。我对volatile变量有疑问,比如:volatile Pool=newpool();如果池构造函数在初始化过程中抛出异常,则池指向何处,如果池构造函数抛出异常,池引用将保持不变——它不会引用部分构造的对象。@ ysavIT是否意味着它仍然指向先前分配的实例?是的,确切地,还是空的,如果引用以前为空。如果您将
      this
      传递到构造函数中的某个位置并引发异常,则将有一个部分构造的对象。;)如果一个对象的构造函数设置了一个
      final
      字段来引用一个新构造的、新编写的、从未通过任何其他方式公开过的持有者;对
      最终
      字段引用的存储是否能保证对对象内项目的所有写入都已完成?引用JLS 17.5:“当另一个线程看到该对象时,该线程将始终看到该对象的
      final
      字段的正确构造版本。它还将看到那些
      final
      字段引用的任何对象或数组的版本,这些字段至少与
      final
      字段一样是最新的。“我想这正是你所问的。谢谢。因此,如果创建对象的唯一目的是将对它的引用放置到最终字段中,并且如果此后它将永远不会暴露于任何会修改它的内容,那么对象本身就不需要担心它的任何字段是否为
      最终
      。知道这个很有用。谢谢。如果一个对象的构造函数设置了一个
      final
      字段来引用一个新构造的、新编写的、从未通过任何其他方式公开过的持有者;对
      最终
      字段引用的存储是否能保证对对象内项目的所有写入都已完成?引用JLS 17.5:“当另一个线程看到该对象时,该线程将始终看到该对象的
      final
      字段的正确构造版本。它还将看到那些
      final
      字段引用的任何对象或数组的版本,这些字段至少与
      final
      字段一样是最新的。“我想这正是你所问的。谢谢。因此,如果创建对象的唯一目的是将对它的引用放置到最终字段中,并且如果此后它将永远不会暴露于任何会修改它的内容,那么对象本身就不需要担心它的任何字段是否为
      最终
      。知道这个很有用。谢谢