【问题标题】:Is a Guava Table thread safe when its backing maps are thread safe?当 Guava Table 的支持映射是线程安全的时,它是线程安全的吗?
【发布时间】:2011-11-05 04:10:23
【问题描述】:

Guava 的Tables.newCustomTable(Map, Supplier) 方法在提供线程安全映射时会返回线程安全表吗?例如:

public static <R, C, V> Table<R, C, V> newConcurrentTable() {
  return Tables.newCustomTable(
      new ConcurrentHashMap<R, Map<C, V>>(),
      new Supplier<Map<C, V>>() {
        public Map<C, V> get() {
          return new ConcurrentHashMap<C, V>();
        }
      });
}

该代码是否真的返回并发表?

【问题讨论】:

  • 你对“并发表”的定义是什么?
  • 好问题。用另一种方式表达我的问题:这些表会以 ConcurrentMap> 不会的方式爆炸吗? “炸毁”是指进入无限循环、抛出异常或执行常规 HashBasedTable 如果您尝试同时在多个线程上读取和写入它会执行的任何其他操作。

标签: java guava


【解决方案1】:

来自文档:“如果多个线程同时访问此表并且其中一个线程修改了表,则必须在外部同步。”

并发支持集合是不够的。

【讨论】:

  • 奇怪的是,javadoc 中的那句话促使我提出这个问题。那好吧。谢谢,凯文。
【解决方案2】:

Kevin Bourrillion 是对的。您构建的映射不是线程安全的技术原因是,即使您使用的映射是线程安全的,表操作也可能不是。举个put的例子,在StandardTable中实现的,Tables.newCustomTable使用的:

public V put(R rowKey, C columnKey, V value) {
  Map<C, V> map = backingMap.get(rowKey);
  if (map == null) {
    map = factory.get();
    backingMap.put(rowKey, map);
  }
  return map.put(columnKey, value);
}

在处理map == null 案例时,线程安全性受到了影响。也就是说,两个或多个线程可以进入该块并为columnKey 创建一个新条目,而最后一个执行backingMap.put(rowKey, map) 的线程最终会覆盖backingMapcolumnKey 的条目,这将导致其他线程执行的put 操作丢失。特别是多线程环境下这个操作的结果是不确定的,相当于说这个操作不是线程安全的。

这个方法的正确实现应该是:

public V put(R rowKey, C columnKey, V value) {
    ConcurrentMap<C, V> map = table.get(rowKey);
    if (map == null) {
        backingMap.putIfAbsent(rowKey, factory.get());
    }
    map = backingMap.get(rowKey);
    return map.put(columnKey, value);
}

我目前正在调查是否可以将ForwardingTable 实现与您想做的一起使用,以获得适当的线程安全ConcurrentTable

但老实说,我认为Table 没有线程安全实现的原因是接口本身不提供任何并发构造,例如putIfAbsentreplace

【讨论】:

  • 在广泛浏览StandardTable 实现之后,我得出一个结论,为了提供线程安全,您只有两个选择:从头开始创建实现,或者提供锁定的包装器每次访问。原因是 row()、column() 或 columnMap() 返回的视图不是线程安全的,无法通过方法重写来修改它们的行为。
  • 对于受限情况,您知道多个线程除了放在不同的行键上之外永远不会做任何事情,这似乎应该是安全的?上下文是我想使用并行线程构建一个表。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-23
  • 2015-05-07
相关资源
最近更新 更多