java - HashMap 卡在了 put 上

标签 java multithreading

我在多线程环境中编码,我看到线程卡在 HashMap.put 上:

 34 Threads
 java.util.HashMap.put(HashMap.java:374) 
 com.aaa.bbb.MyClass.getDefinitionMap().

调查 HashMap 方法,我发现该方法是同步的:

@Override
public synchronized Map<String,String> getDefinitionMap() {
        //truncated some code here...
        colDefMap = new HashMap<String,String>();           
        for (CD cd : (List<CD>)cm.getDef()) {
            colDefMap.put(cd.getIdentifier(),cd);
        }
    return colDefMap;
}

因此在切换到ConcurrentHashMap 后,从方法签名中删除同步关键字并重新启动应用程序服务器 - 问题已解决。

我的问题是为什么同步方法在这种情况下不足以保护 map 免受并发访问?

最佳答案

你不说这有多“卡”,你是否真的有死锁或瓶颈。

我希望发布的代码是一个瓶颈,几乎所有线程都试图访问同一个对象,等待获取同步方法使用的锁。 cm.getDef 所做的任何事情都可能需要一段时间,并且一次只有一个线程可以取得进展。因此,同步确实可以保护数据免受并发访问,只是以吞吐量为代价。

这符合 the Java concurrency tutorial 中给出的“饥饿”定义:

Starvation describes a situation where a thread is unable to gain regular access to shared resources and is unable to make progress. This happens when shared resources are made unavailable for long periods by "greedy" threads. For example, suppose an object provides a synchronized method that often takes a long time to return. If one thread invokes this method frequently, other threads that also need frequent synchronized access to the same object will often be blocked.

正如您观察到的,切换到 ConcurrentHashMap 是一个很好的改进。 ConcurrentHashMap 避免将线程锁定在整个映射之外,并支持并发更新,请参阅 the API doc (我的重点):

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. 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.

您可能会考虑缓存 cm.getDef 所做的任何事情,这样您就不必每次都调用它,但是这当然取决于您的要求。

关于java - HashMap 卡在了 put 上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38383864/

相关文章:

java - Android小部件未多次更新

java - 从另一个 Java 应用程序停止/启动/重新启动 Java 应用程序

java - 如何使用AOP计算 Controller 类中调用的所有内部服务的响应时间

Java:什么对象比较合适?

java - 在我的 Android 应用程序中未找到类异常

java - org.springframework.web.servlet.PageNotFound noHandlerFound警告: No mapping found for HTTP request with URI

解锁后的Java线程执行顺序

python - 在 Tkinter 中执行函数期间程序卡住

java - Java中的ThreadFactory使用

c++ - C++线程创建/删除与线程停止/恢复