我应该同步静态volatile变量吗?

Ale*_*lex 7 java volatile thread-safety

关于这个问题有几个问题,但大多数都围绕这个问题,因为这不是问题的意图.

如果我班上有静态易失性:

private static volatile MyObj obj = null;
Run Code Online (Sandbox Code Playgroud)

在下面的方法中我做:

public MyObj getMyObj() {
    if (obj == null) {
        obj = new MyObj();// costly initialisation
    }
    return obj;
}
Run Code Online (Sandbox Code Playgroud)

我需要同步以确保只有一个线程写入字段,或者任何写入是否会立即显示给评估obj == null条件的其他线程?

换句话说:volatile是否会让你不得不同步访问静态变量上的写入?

Jon*_*eet 8

你肯定会需要一些类型的锁,以确保只有一个线程写入到外地的.无论波动性如何,两个线程都可以"看到" obj为空,然后两个线程都开始使用当前代码进行初始化.

就个人而言,我会选择以下三个选项之一:

  • 在类加载时初始化(知道这将是惰性的,但不像在getMyObj第一次调用之前那样懒惰):

    private static final MyObj obj = new MyObj();
    
    Run Code Online (Sandbox Code Playgroud)
  • 使用无条件锁定:

    private static MyObj obj;
    private static final Object objLock = new Object();
    
    public static MyObj getMyObj() {
        synchronized(objLock) {
            if (obj == null) {
                obj = new MyObj();
            }
            return obj;
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 以这种方式使用嵌套类来实现懒惰:

    public static MyObj getMyObj() {
        return MyObjHolder.obj;
    }
    
    private static class MyObjHolder {
        static final MyObj obj = new MyObj();
    }
    
    Run Code Online (Sandbox Code Playgroud)