Java静态 block 线程安全

标签 java multithreading

我正在研究 Java 11 并发模型,我发现可以通过 LazyHolder pattern 获得真正的单例。 .特别是,该页面说:

Since the class initialization phase is guaranteed by the JLS to be sequential, i.e., non-concurrent, no further synchronization is required...

好的,所以我明白静态字段只按顺序初始化一次(所以

public class DatabaseQueries {

  private static Map<DatabaseActions, String> database = new HashMap<>();

  public static Map<DatabaseActions, String> getDatabase() {
    return Collections.unmodifiableMap(database);
  }

  static {
    database.put(
      DatabaseActions.LIST_CHIHUAHUA,
      "SELECT id, nome, immagine FROM chihuahua ORDER BY data_nascita DESC"
    );

    // more...

  }

}

上面的代码线程安全吗?即使我有一个静态 block 和一个单独的 map 静态初始化!


我在 this 找到了回答:

Static class initialization is guaranteed to be thread-safe by Java.

上面我有一个静态 block 和一个静态变量,这有什么区别吗?是否都在类启动时初始化?

所以我的问题是静态 block 和静态变量(在静态 block 之外)是否都保证不会导致多线程问题

最佳答案

你写的

Even if I have a static block AND a separate static initialization of a map!

这表明错误的心态。您没有单独的初始化。

代码

public class DatabaseQueries {
  private static Map<DatabaseActions, String> database = new HashMap<>();
  static {
    database.put(
      DatabaseActions.LIST_CHIHUAHUA,
      "SELECT id, nome, immagine FROM chihuahua ORDER BY data_nascita DESC"
    );
  }
}

等同于

public class DatabaseQueries {
  private static Map<DatabaseActions, String> database;
  static {
    database = new HashMap<>();
    database.put(
      DatabaseActions.LIST_CHIHUAHUA,
      "SELECT id, nome, immagine FROM chihuahua ORDER BY data_nascita DESC"
    );
  }
}

static 字段的所有初始化器(编译时常量除外)与所有 static {} block 合并为一个初始化器,按照它们在类声明。

线程安全适用于单个结果初始化器的完成和初始化数据的后续读取。

所以如果映射在类初始化后从未被修改过,它就是线程安全的。没有必要,但强烈建议强制执行“初始化后不修改”规则:

public class DatabaseQueries {

  private static final Map<DatabaseActions, String> database;
  static { // keep variable declaration and initializer close for readability
    Map<DatabaseActions, String> map = new HashMap<>();// mutable ref during initialization
    map.put(
      DatabaseActions.LIST_CHIHUAHUA,
      "SELECT id, nome, immagine FROM chihuahua ORDER BY data_nascita DESC"
    );
    // more...
    database = Collections.unmodifiableMap(map);// enforce read-only
  }

  public static Map<DatabaseActions, String> getDatabase() {
    return database;// no wrapping necessary, it’s already wrapped
  }
}

关于Java静态 block 线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58993352/

相关文章:

java - String.replace() 和正则表达式。模式中的正则表达式符号是否会影响?

java - LWJGL 按键事件状态不起作用

java - 多线程/ volatile 变量/条件/循环的特殊行为(Java)

java - ConcurrentHashMap 如何处理重新散列?

c++ - 我这里可以不使用线程同步吗?

winforms - 在应用程序中打开太多线程是否不好?

java - 如何将数组列表放入java中的组合框中?

java - 为 MultipartFormData java Play Framework 2 创建 fakeRequest

java - activemq jndi tomcat错误

C#线程内存异常