Java中的对象初始化是原子的吗?

Java中的对象初始化是原子的吗?,java,atomic,Java,Atomic,我知道myObject1=myObject2是原子的,但下面的代码行是原子的吗 Object obj1 = new Object(); 它实际上可以被挂在初始化引用的中间吗? < P>它不是原子的。没有什么可以阻止您在对象构造函数中放入睡眠,或无限循环,或在构造函数中抛出异常 注意:虽然可能,但这些都是反模式,不推荐使用。这行不是原子的。发生了两件事:首先,创建了一个通常不是原子的新对象,然后将对该对象的引用指定给变量obj1。比如说,Thread1和Thread2执行的行在随机时刻观察变量的

我知道myObject1=myObject2是原子的,但下面的代码行是原子的吗

Object obj1 = new Object();

它实际上可以被挂在初始化引用的中间吗?

< P>它不是原子的。没有什么可以阻止您在对象构造函数中放入睡眠,或无限循环,或在构造函数中抛出异常


注意:虽然可能,但这些都是反模式,不推荐使用。

这行不是原子的。发生了两件事:首先,创建了一个通常不是原子的新对象,然后将对该对象的引用指定给变量obj1。比如说,Thread1和Thread2执行的行在随机时刻观察变量的状态。为了简单起见,Thread2可以观察到三种状态假设对象创建本身是原子的

obj1==null,未创建对象 obj1==null,对象已创建,但对它的引用尚未分配给变量 obj1!=null,则该行已完全执行 原子性意味着Thread2可能只观察到状态1和状态3,但必须强制执行。使其原子化的一种方法是在本例中通过同步obj1是一个类字段:

public synchronized Object getObj() {
    if (obj1 == null)
        obj1 = new Object();

    return obj1;
}

第一个调用此方法的线程将初始化该字段,进一步的调用将只返回变量。由于互斥,创建对象后,线程不可能在obj1中观察到null,因为不同线程的方法调用不能重叠。

引用分配是原子的。在任何情况下,引用本身都不会被部分分配,这显然会导致VM有时崩溃。它将为null或不为null。在指定引用之前,对象的构造不是原子的,但是在构造过程完成之前,您将无法访问要指定给引用的新对象


有趣的是,引用分配可能发生在与主内存不同步的芯片上的缓存内存中。这意味着其他线程不会立即看到分配。有两种方法可以确保引用分配被推送到主存,其他线程可以立即看到它。1将引用声明为易失性,2将引用分配放在同步块中退出同步块会将缓存的引用提交到主存

您是否担心obj1被视为无效引用,或者关于在对象字段初始化之前观察到的对象的引用,或者其他什么?根据上下文,原子可能意味着一些不同的事情。这里的背景或场景是什么?是否涉及多线程?是的,我是指多线程。我不知道还有其他的概念。我只知道原子操作:在构造函数中抛出异常并不完全是一种反模式,但你的观点是正确的。谢谢你,它确实有意义。如果有空的构造函数,它会是原子的吗?谢谢,这很有道理:你说仅仅创建对象不是原子的,这让我很好奇。我从来没有想过。Java内存模型还允许第四种状态:obj1!=null,但构造函数尚未完成。这是可能的,因为故障execution@Joni是的,种族是纯粹的邪恶!