当 Guava Table 的支持映射是线程安全的时,它的线程安全吗?
Guava 的 Tables.newCustomTable(Map, Supply) 方法在提供线程安全映射时返回线程安全表?例如:
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>();
}
});
}
该代码实际上返回并发表吗?
Will Guava's Tables.newCustomTable(Map, Supplier) method return thread safe tables when supplied with thread safe maps? For example:
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>();
}
});
}
Does that code actually return concurrent tables?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
来自文档:“如果多个线程同时访问此表,并且其中一个线程修改了该表,则必须在外部进行同步。”
并发支持集合还不够。
From the doc: "If multiple threads access this table concurrently and one of the threads modifies the table, it must be synchronized externally."
Concurrent backing collections aren't enough.
凯文·伯里利恩是对的。您构造的映射不是线程安全的技术原因是,即使您使用的映射是线程安全的,表操作也可能不是。让我举一个 put 的例子,它是在
StandardTable
中实现的,它是由Tables.newCustomTable
使用的:在处理
map = 时,线程安全受到损害。 = null
情况。也就是说,两个或多个线程可以进入该块并为columnKey
创建一个新条目,最后一个执行backingMap.put(rowKey, map)
最终将覆盖backingMap
中columnKey
的条目,这会导致其他线程执行的put
操作丢失。特别是在多线程环境下这个操作的结果是不确定的,相当于说这个操作不是线程安全的。此方法的正确实现是:
我目前正在调查是否可以将
ForwardingTable
实现与您想要执行的操作一起使用,以获得正确的线程安全ConcurrentTable
。但说实话,我认为
Table
没有线程安全实现的原因是接口本身不提供任何并发构造,例如putIfAbsent
或替换
。Kevin Bourrillion is right. The technical reason for the map you've constructed not to be thread safe is that even if the maps you are using are thread safe, the table operations may not be. Let me give an example of put, as implemented in the
StandardTable
, which is used byTables.newCustomTable
:Thread safety is compromised in the handling of the
map == null
case. Namely, two or more threads could enter that block and create a new entry for thecolumnKey
and the last one to perform abackingMap.put(rowKey, map)
would ultimately override the entry for thecolumnKey
in thebackingMap
, which would lead to the loss ofput
operations performed by other threads. In particular the result of this operation in a multithreaded environment is non-deterministic, which is equivalent to saying that this operation is not thread safe.The correct implementation of this method would be:
I'm currently investigating if it is possible to use the
ForwardingTable
implementation together with what you've wanted to do, to get a properly thread safeConcurrentTable
.But to be honest, I think the reason there is no thread-safe implementation of the
Table
is that the interface itself doesn't provide any concurrency constructs, such asputIfAbsent
orreplace
.