Kevin Bourrillion是对的。您构建的地图不是线程安全的技术原因是,即使您使用的地图是线程安全的,表操作也可能不是。让我给放的例子,如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)
的最后一个将最终覆盖backingMap
中的columnKey
的条目,这将导致丢失由其他执行的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
实现的原因是接口本身不提供任何并发结构,如putIfAbsent
或replace
。
你对“并发表”的定义是什么? –
好问题。用另一种方式来解释我的问题:这些表会不会以一种并发地图>的方式炸毁?而通过“爆炸”,我的意思是进入无限循环,抛出异常,或者做任何其他常规HashBaseTable将做的事情,如果你试图在多线程上同时读取和写入它。 –