Java 在多线程环境中按以下方式构造对象安全吗

Java 在多线程环境中按以下方式构造对象安全吗,java,concurrency,constructor,Java,Concurrency,Constructor,我的问题如下: 说所有对象都将一个接一个地一致构建,这绝对正确吗?我的意思是,每一个新对象都是在前一个对象之后构建的。换句话说,每个新对象的时间戳都比前一个对象大 final关键字如何影响此行为?据我所知,如果所有对象字段都是final,那么它会以某种方式使构造函数原子化。在初始化所有final字段之前,不会发布引用 构建此类对象的最佳实践是什么?Is足以使lastRevision原子化,或者newInstance应声明为synchronized 原子性保证仅对incrementAndGet

我的问题如下:

  • 说所有对象都将一个接一个地一致构建,这绝对正确吗?我的意思是,每一个新对象都是在前一个对象之后构建的。换句话说,每个新对象的时间戳都比前一个对象大
  • final
    关键字如何影响此行为?据我所知,如果所有对象字段都是
    final
    ,那么它会以某种方式使构造函数原子化。在初始化所有
    final
    字段之前,不会发布引用
  • 构建此类对象的最佳实践是什么?Is足以使
    lastRevision
    原子化,或者
    newInstance
    应声明为
    synchronized
      • 原子性保证仅对
        incrementAndGet()
        调用有效。因此,是的,每个新对象的修订都是连续的,这就是原子数据类型的目的。因此,为了回答您的问题:不能保证多个线程将按照调用
        incrementAndGet()
        的相同顺序执行构造函数中的语句。要实现这一点,您必须将此部分放入
        synchronized
        块中

      • final
        s在这里没有帮助。它们是纯逻辑特性,不允许在对象创建后对字段进行变异

      • 如果您确实需要时间戳与修订保持一致,则必须引入某种形式的线程同步。您可以使整个方法同步,然后
        lastRevision
        不必是原子的
      此外,无论您决定做什么,您可能还希望检查
      System.nanoTime()
      本身提供的保证

      说所有对象都将被构造是绝对正确的吗 始终如一

      否。
      lastRevision.incrementAndGet()
      是一个阻塞调用,但调度程序可以在接收到第一个ID后暂停第一个线程,然后在第二个线程接收到第二个ID后恢复该线程,这意味着两个构造函数将同时执行

      换句话说,每个新对象的时间戳都比 上一个

      不,见上文

      final
      关键字如何影响此行为

      没有

      据我所知,如果所有对象字段都是最终字段,那么 构造函数在某种程度上是原子的

      不对。如果每个字段都是final,那么类是不可变的*,这使得它隐式地是线程安全的

      构建此类对象的最佳实践是什么?这就足够了
      lastRevision
      原子或
      newInstance
      应声明为已同步

      如果必须连续创建每个实例,则应同步
      newInstance
      。一旦是,原子整数就没有意义了。即使这样做,时间戳也可能是相同的,这取决于底层系统时钟的分辨率


      *嗯,不完全是这样。如果每个字段都是最终字段,并且本身也是不可变的

      public class DataEvent {
          private static final AtomicInteger lastRevision = new AtomicInteger();
          private final int revision;
          private final long threadId;
          private final long timestamp;
      
          private DataEvent(int revision) {
              this.revision = revision;
              this.threadId = Thread.currentThread().getId();
              this.timestamp = System.nanoTime();
          }
      
          public static DataEvent newInstance() {
              return new DataEvent(lastRevision.incrementAndGet());
          }
      }