假设只有一台服务器(没有负载均衡器等),如果Javaservlet中的请求写入 static ConcurrentHashMap
,在从Map中删除Map条目之前,Map条目是否立即可用于所有后续servlet请求?换句话说,在对Map的写入返回后,来自另一个servlet请求的后续请求是否有可能找不到Map的任何内容?例如:
import java.util.concurrent.ConcurrentHashMap;
public class IntentTracker {
private static ConcurrentHashMap<String, AccountUpdateRequest> updateForIntent = new ConcurrentHashMap<>();
// static access only
private IntentTracker() {}
public static void put(String intentId, AccountUpdateRequest accountUpdate) {
updateForIntent.put(intentId, accountUpdate);
}
public static AccountUpdateRequest remove(String intentId) {
return updateForIntent.remove(intentId);
}
}
我知道这里的理想情况是使用持久数据存储进行存储和检索,但我想了解 ConcurrentHashMap
会引起一个问题。
1条答案
按热度按时间s4chpxco1#
假设只有一台服务器(没有负载均衡器等),如果Javaservlet中的请求写入静态concurrenthashmap,那么在从Map中删除该条目之前,Map条目是否立即可用于所有后续的servlet请求?
多线程编程中的一个问题是定义“后续”和描述事件时间顺序的类似术语。一些相关的承诺
ConcurrentHashMap
那是什么所有线程都将感知相同的单元素Map修改顺序。
所有线程都将遵循与修改顺序一致的单个元素检索顺序。
Iterator
是的,Spliterator
s、 以及Enumeration
Map内容的s将反映Map在特定时间点相对于单个元素修改顺序的状态(没有承诺这个时间点与迭代器的示例化有关,等等…)说明书上说。。。
检索反映了最近完成的更新操作在开始时的结果。
... 但这必须被视为一个意图声明,而不是一个规范。接下来是这个更正式的表达,它实际上意味着什么:
给定键的更新操作与该键的任何(非null)检索(报告更新值)具有“发生在”关系
实际上,其目的是提供您想要看到的行为,但是从另一个Angular 来看待它在逻辑上更为正确:在没有任何其他修改的情况下,一个线程的读操作r是否感知到另一个线程对Map执行的特定修改w定义了r是发生在w之前还是之后。
换句话说,在对Map的写入返回后,来自另一个servlet请求的后续请求是否有可能找不到Map的任何内容?
如果我们使用“后续”的适当定义,那么答案就是“不”,因为一个请求是否“后续”取决于(除其他外)一个请求是否看到另一个请求对Map的修改。但是如果一个线程确实看到了该修改(或者之后发生的另一个修改以全局一致的顺序对Map进行修改),那么它还将看到另一个线程在修改Map之前在共享内存上执行的所有其他操作。
这并不意味着在一个线程对Map的修改对其他线程可见之前,您必须担心长时间的延迟。你没有。关于单元素操作的计时和内存排序考虑与使用普通的
HashMap
并在互斥锁的保护下执行每次更新和每次读取,但通常不涉及锁ConcurrentHashMap
.