简体   繁体   English

为什么ConcurrentHashMap中的computeIfAbsent()方法行为不一致?

[英]Why is the computeIfAbsent() method in ConcurrentHashMap behaving inconsistently?

I have a Java 8 web application running on Apache Tomcat 9. The invocation of ConcurrentHashMap 's computeIfAbsent() method is not returning or is taking too long to return. 我在Apache Tomcat 9的调用一个Java 8 Web应用程序运行ConcurrentHashMapcomputeIfAbsent()方法没有返回或时间过长返回。

In the code given below, the line ' Adding to Map ' is printed and the line ' Map : ' does not print at all in some cases as if the executing thread is trapped within the method. 在下面给出的代码中,打印“ 添加到地图 ”行,并且在某些情况下根本不打印“ Map: ”行,就像执行的线程被捕获在方法中一样。 Once it gets trapped any subsequent calls to the same method with the same id also get stuck and never return while calls with a different id return immediately. 一旦被捕获,对具有相同id的相同方法的任何后续调用也会卡住并且永远不会返回,而具有不同id调用立即返回。 Testing on another instance with a different id , the computeIfAbsent() method returned after 2 minutes. 在另一个具有不同id实例上进行测试,在2分钟后返回computeIfAbsent()方法。 The maximum concurrent calls executing the code at the time of testing would be around 20 only. 在测试时执行代码的最大并发调用数仅为20左右。 As per my understanding computeIfAbsent() is thread safe. 根据我的理解, computeIfAbsent()是线程安全的。 What is wrong here? 这有什么不对?

private Map<String, Map<String, SomeClass>> aMap = new ConcurrentHashMap<>();
LOGGER.debug("Adding to Map");
Map<String, SomeClass> m = aMap
            .computeIfAbsent(id, k -> Collections.synchronizedMap(new HashMap<>()));
LOGGER.debug("Map : " + m);

Any subsequent calls to the same method with same id also got stuck and never returned while calls with different id returned immediately ? 对具有相同id的相同方法的任何后续调用也会被卡住并且在具有不同id的调用立即返回时永远不会返回?

Yes, If the computation is in progress any subsequent computation calls of that id will be blocked 是,如果计算正在进行,则将阻止该ID的任何后续计算调用

If the specified key is not already associated with a value, attempts to compute its value using the given mapping function and enters it into this map unless null. 如果指定的键尚未与值关联,则尝试使用给定的映射函数计算其值,并将其输入此映射,除非为null。 The entire method invocation is performed atomically, so the function is applied at most once per key. 整个方法调用是以原子方式执行的, 因此每个键最多应用一次该函数。 Some attempted update operations on this map by other threads may be blocked while computation is in progress so the computation should be short and simple, and must not attempt to update any other mappings of this map. 在计算正在进行时可能会阻止其他线程对此映射进行的某些尝试更新操作,因此计算应该简短,并且不得尝试更新此映射的任何其他映射。

The maximum concurrent calls executing the code at the time of testing would be around 20 only. 在测试时执行代码的最大并发调用数仅为20左右。 As per my understanding ? 据我所知?

No, It completely depends on how many buckets are available in that map 不,这完全取决于该地图中有多少可用的存储桶

In ConcurrentHashMap , at a time any number of threads can perform retrieval operation but for updation in object, thread must lock the particular segment in which thread want to operate.This type of locking mechanism is known as Segment locking or bucket locking. ConcurrentHashMap中 ,任何数量的线程都可以执行检索操作,但是对于对象的更新,线程必须锁定线程想要操作的特定段。这种类型的锁定机制称为段锁定或桶锁定。 Hence at a time 16 updation operations can be performed 因此,在时间16可以执行更新操作

computeIfAbsent() is thread safe ? computeIfAbsent()是线程安全的吗?

Yes, it is thread safe ConcurrentHashMap 是的,它是线程安全的ConcurrentHashMap

A hash table supporting full concurrency of retrievals and high expected concurrency for updates. 一个哈希表,支持检索的完全并发和更新的高预期并发性。 This class obeys the same functional specification as Hashtable, and includes versions of methods corresponding to each method of Hashtable. 该类遵循与Hashtable相同的功能规范,并包括与Hashtable的每个方法相对应的方法版本。 However, even though all operations are thread-safe, retrieval operations do not entail locking, and there is not any support for locking the entire table in a way that prevents all access. 但是,即使所有操作都是线程安全的,检索操作也不需要锁定,并且不支持以阻止所有访问的方式锁定整个表。 This class is fully interoperable with Hashtable in programs that rely on its thread safety but not on its synchronization details. 在依赖于线程安全但不依赖于其同步细节的程序中,此类可与Hashtable完全互操作。

Honestly i'm not the one who designed and implemented ConcurrentHashMap , but through the internet i found an article for java 8 ConcurrentHashMap improvements , I assume this might causing the delay in first call. 老实说,我不是那个设计和实现ConcurrentHashMap ,但通过互联网,我找到了一篇关于java 8 ConcurrentHashMap改进的文章,我认为这可能会导致第一次调用的延迟。

Lazy table initialization that minimizes footprint until first use 延迟表初始化,在首次使用之前最小化占用空间

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么 ConcurrentHashMap::putIfAbsent 比 ConcurrentHashMap::computeIfAbsent 快? - Why ConcurrentHashMap::putIfAbsent is faster than ConcurrentHashMap::computeIfAbsent? ConcurrentHashMap computeIfAbsent - ConcurrentHashMap computeIfAbsent Java ConcurrentHashMap computeIfAbsent() 方法是否支持基于键的“锁定”? - Does Java ConcurrentHashMap computeIfAbsent() method support key-based “locking”? 为什么 ConcurrentHashMap.computeIfAbsent() 为已经存在的键增加计数器? - Why does ConcurrentHashMap.computeIfAbsent() increment the counter for an already present key? 检查ConcurrentHashMap的computeIfAbsent是否更改了某些内容 - Check if computeIfAbsent of ConcurrentHashMap changed something ConcurrentHashMap computeIfAbsent 判断是否是第一次 - ConcurrentHashMap computeIfAbsent tell if first time or not computeIfAbsent 如何随机使 ConcurrentHashMap 失败? - How does computeIfAbsent fail ConcurrentHashMap randomly? 为什么ConcurrentHashMap中的get方法是阻塞的? - Why get method in ConcurrentHashMap is blocking? ConcurrentHashMap.computeIfAbsent threadsafe中的赋值是什么? - Is an assignment inside ConcurrentHashMap.computeIfAbsent threadsafe? 嵌套时,ConcurrentHashMap的computeIfAbsent线程是否安全? - Is ConcurrentHashMap's computeIfAbsent thread safe, when nested?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM