简体   繁体   English

object 初始化在 Java 中是原子的吗?

[英]Is object initialization atomic in Java?

I know myObject1 = myObject2 is atomic, but is following line of code atomic?我知道myObject1 = myObject2是原子的,但是下面的代码行是原子的吗?

Object obj1 = new Object();

Can it actually be suspended in the middle of initializing a reference?它实际上可以在初始化引用的中间暂停吗?

It is not atomic.它不是原子的。 There's nothing stopping you from putting a sleep inside the Object constructor, or an infinite loop, or throwing an exception inside the constructor.没有什么能阻止你在 Object 构造函数中sleep ,或者无限循环,或者在构造函数中抛出异常。

NOTE: Although possible, these are all anti-patterns and are not recommended.注意:尽管可能,但这些都是反模式,不推荐使用。

This line is not atomic.这条线不是原子的。 Two things happen: first, new Object is created (which is in general is not atomic), and then the reference to this object is assigned to the variable obj1 .发生了两件事:首先,创建了新的Object (通常不是原子的),然后将这个 object 的引用分配给变量obj1 Say, the line executed by Thread1 , and Thread2 observes the state of the variable at a random moment.比如说,由Thread1执行的行和Thread2观察变量的 state 。 There are three states Thread2 can observe (for simplicity assume object creation itself is atomic), Thread2可以观察到三种状态(为简单起见,假设 object 创建本身是原子的),

  1. obj1 == null , the object is not created obj1 == null ,未创建 object
  2. obj1 == null , the object is created, but the reference to it is yet to be assigned to the variable obj1 == null , object 已创建,但对它的引用尚未分配给变量
  3. obj1 != null , the line is fully executed obj1 != null ,该行已完全执行

Atomicity would suggest that Thread2 may observe only state 1 and 3, but it has to be enforced.原子性表明Thread2可能仅观察 state 1 和 3,但必须强制执行。 One way to make it atomic is via synchronization (in this example obj1 is a class field):使其原子化的一种方法是通过同步(在此示例中, obj1是 class 字段):

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

    return obj1;
}

First thread calling this method will initialize the field, and further calls will simply return the variable.第一个调用此方法的线程将初始化该字段,进一步调用将简单地返回该变量。 Due to mutual exclusion, it is not possible for a thread to observe null in obj1 after the object is created, since method calls by different threads cannot overlap.由于互斥,创建null后,线程不可能观察到obj1中的null,因为不同线程的方法调用不能重叠。

The reference assignment is atomic.引用分配是原子的。 There is no condition under which the reference itself will be partly assigned (this would obviously cause the VM to crash at times).没有条件可以部分分配引用本身(这显然会导致 VM 有时崩溃)。 It will either be null or not-null.它将是 null 或不为空。 The construction of the object before the reference is assigned isn't atomic, but you won't get access to the new object to assign to the reference until the construction process is finished.在分配引用之前 object 的构造不是原子的,但是在构造过程完成之前,您将无法访问新的 object 以分配给引用。

Interestingly, the reference assignment can occur in cached memory on the chip that isn't synchronized with main memory.有趣的是,参考分配可能发生在与主 memory 不同步的芯片上缓存的 memory 中。 This means other threads won't see the assignment right away.这意味着其他线程不会立即看到分配。 There are two ways to ensure that the reference assignment is pushed through to main memory where other threads can immediately see it.有两种方法可以确保将引用分配推送到主 memory 其他线程可以立即看到它。 (1) declare the reference as volatile and (2) put the reference assignment in a synchronized block (exiting the synchronized block will commit the cached reference to main memory) (1) 将引用声明为 volatile 并 (2) 将引用分配放在同步块中(退出同步块会将缓存的引用提交到主内存)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM