首页 > 解决方案 > 空引用的安全初始化

问题描述

我想知道对于初始化为 null 的非最终字段(如果有)存在哪些发布保证。

考虑以下代码段:

public class MyClass {

    private final CopyOnWriteArrayList<Inner> list = new CopyOnWriteArrayList<>();

    //called by thread 1
    public void init() {
        // initialise Inner instance
        list.add(new Inner());
    }

    //called by thread 2
    public void doSomething() {
        for (Inner i : list) {
            // access non-final field
            Object ref = i.ref;
            // do something
            // ...
            // ...

            // potentially set i.ref
        }
    }

    private static class Inner {
        // initialised by thread 1
        Object ref = null;
    }
}

假设doSomething()总是由线程 2 调用,这安全吗?对线程 2 第一次访问它时会看到什么做出了哪些保证?线程 2 是否有可能看到非空的东西?

JMM 在哪里描述了围绕这种情况的语义?

标签: javathread-safetyjava-memory-modelsafe-publication

解决方案


JVM将保证您不会凭空看到值,所以除了它之外的任何东西null 都是不可能的,以防它List不是空的(在这个例子中,当然)。如果涉及到不同的线程(比方说Thread3)会改变您的列表(向其中添加元素),则Thread2可以看到这些更新。请注意,单个方法CopyOnWriteArrayList是线程安全的;你的方法doSomething 不是

有关详细信息,请参阅JLS或出色的(而且相当复杂,可能只是对我而言)Aleksey 文章


推荐阅读