[英]Is object initialization atomic in Java?
我知道myObject1 = myObject2
是原子的,但是下面的代码行是原子的吗?
Object obj1 = new Object();
它实际上可以在初始化引用的中间暂停吗?
它不是原子的。 没有什么能阻止你在 Object 构造函数中sleep
,或者无限循环,或者在构造函数中抛出异常。
注意:尽管可能,但这些都是反模式,不推荐使用。
这条线不是原子的。 发生了两件事:首先,创建了新的Object
(通常不是原子的),然后将这个 object 的引用分配给变量obj1
。 比如说,由Thread1
执行的行和Thread2
观察变量的 state 。 Thread2
可以观察到三种状态(为简单起见,假设 object 创建本身是原子的),
obj1 == null
,未创建 objectobj1 == null
, object 已创建,但对它的引用尚未分配给变量obj1 != null
,该行已完全执行原子性表明Thread2
可能仅观察 state 1 和 3,但必须强制执行。 使其原子化的一种方法是通过同步(在此示例中, obj1
是 class 字段):
public synchronized Object getObj() {
if (obj1 == null)
obj1 = new Object();
return obj1;
}
第一个调用此方法的线程将初始化该字段,进一步调用将简单地返回该变量。 由于互斥,创建null
后,线程不可能观察到obj1
中的null,因为不同线程的方法调用不能重叠。
引用分配是原子的。 没有条件可以部分分配引用本身(这显然会导致 VM 有时崩溃)。 它将是 null 或不为空。 在分配引用之前 object 的构造不是原子的,但是在构造过程完成之前,您将无法访问新的 object 以分配给引用。
有趣的是,参考分配可能发生在与主 memory 不同步的芯片上缓存的 memory 中。 这意味着其他线程不会立即看到分配。 有两种方法可以确保将引用分配推送到主 memory 其他线程可以立即看到它。 (1) 将引用声明为 volatile 并 (2) 将引用分配放在同步块中(退出同步块会将缓存的引用提交到主内存)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.