java - 我应该同步静态易失变量吗?

标签 java thread-safety volatile

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

如果我的类中有静态 volatile:

private static volatile MyObj obj = null;

在下面的方法中我这样做:

public MyObj getMyObj() {
    if (obj == null) {
        obj = new MyObj();// costly initialisation
    }
    return obj;
}

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

换句话说:volatile 是否让您不必同步对静态变量的写入访问?

最佳答案

您肯定需要某种 类型的锁定来确保只有一个线程写入该字段。无论波动如何,两个线程都可以“看到”obj 为空,然后都开始使用您当前的代码进行初始化。

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

  • 在类加载时初始化(知道这会很懒,但不像等到首次调用 getMyObj 那样懒):

    private static final MyObj obj = new MyObj();
    
  • 使用无条件锁定:

    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;
        }
    }
    
  • 以这种方式使用嵌套类来实现惰性:

    public static MyObj getMyObj() {
        return MyObjHolder.obj;
    }
    
    private static class MyObjHolder {
        static final MyObj obj = new MyObj();
    }
    

关于java - 我应该同步静态易失变量吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10697451/

相关文章:

java - 具有最终局部变量对象引用的安全发布

c++ - boost::uuids::random_generator 和多线程的唯一性

java - 将数组变量的值赋给自身?

java - 在数据竞争期间,线程能否读取 volatile 变量的初始空值?特别是在构造函数中为其分配了非空值时?

java - SonarQube Eclipse 插件 : incremental mode for changed files only

java - 如何使视频仅从按钮开始?

java - 如何使用@PostConstruct 在无状态 bean EJB3 中创建计时器?

java - 在JAVA中读取格式为PKCS1的RSA私钥

c++ - 当永远不会同时访问共享托管对象时,在生产者和消费者之间使用 std::shared_ptr 是否安全?

有人可以解释以下代码语句吗?