java - 我哪里不是线程安全的?

标签 java multithreading thread-safety

我正在使用一个对象,它大致用作字符串映射的包装器:

public class Wrapper {
  private Map<String, String> values;
  private Formatter formatter;

  public BigDecimal getSpecialValue() {
    String result = values.get("Special");
    return formatter.formatNumber(result);
  }
}

上述格式化程序大致用作 SimpleDateFormat 的映射器

 public class Formatter {
   private static final NumberFormat NUMBER_FORMAT;

   public BigDecimal formatNumber(String s) {
     Number num = NUMBER_FORMAT.parse(s);
     if (num instanceof Integer) {
       return new BigDecimal((Integer) num);
     } else if (num instanceof Double) {
       return new BigDecimal((Double) num);
     } ...
   }
 }

当我同时通过多个线程访问 getSpecialValue() 方法时,会出现一些行为,这只能通过并发访问来解释,例如可能会出现 NumberFormatExceptionParseException,其中解析的字符串是 .430.430 而不是 .430 等等。

有两个方面引起了我的兴趣: 1.) 包装器只能以只读方式访问。尽管对集合的访问不是同步的,但我的印象是这应该始终有效。 2.) 在第一次尝试发现问题时,我更改了 Wrapper 类的构造函数以执行 formatNumber 方法(显然是单线程),这消除了所有异常下执行。

谁能解释一下?

编辑: Wrapper 类中的映射被填充到构造函数中,这通常发生在单线程中。之后包装器被设计成 map 是不可变的。

最佳答案

只需在 jdoc 中搜索“thread”,就会发现 NumberFormat 类的以下内容:数字格式通常不同步。建议为每个线程创建单独的格式实例。如果多个线程并发访问一个格式,则必须在外部进行同步。

关于java - 我哪里不是线程安全的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8911128/

相关文章:

c++ - QAbstractItemModel 线程安全

c# - 在 c# web 服务中超时的锁

c# - UDP 绑定(bind)方法

java - 为什么在指定类型的HashSets中不能推断出equals?

java - 无法从 ReactiveCouchbaseRepository 中删除项目

java8 流 api 抛出不兼容的类型 : Object[] cannot be converted to Integer[] when converting String array to Integer array

multithreading - iPhone : address book is erased sometimes

c++ - std::atomic 的正确用法

c++ - 是什么让我的 C++ ctime 相关函数行为异常?

java - 解析 Java 路径的安全方法