java - 如何在允许同时读取线程的同时同步 HashMap?

标签 java multithreading

我正在使用以下HashMap:

HashMap<String,String> hm = new HashMap<String,String>();

在单独线程中运行的三个不同的 Runnable 将从 hm 读取,而第四个线程的 Runnable 将添加和删除键/值条目从 map 上。根据the Java documentation ,只要多个线程可能同时与该映射交互,我就应该同步对该映射的访问。但是,出于性能原因,我不希望三个读取器线程相互阻塞,因为它们只是从 map 中读取。我只希望在第四个线程添加/删除映射条目时发生阻塞。根据我的理解,调用Collections.synchronizedMap(...)将同步任何类型的 map 访问。我怎样才能实现这个目标?

最佳答案

should synchronize access to this map whenever multiple threads may concurrently interact with it. However, for performance reasons, I don't want the three reader threads to block each other since they're simply reading from the map.

尽管读取器不需要阻塞,但您确实需要在读取和写入时同步两者上的内存,否则读取器可能会获得部分更新的映射,从而生成一个异常(exception)。请参阅tutorial on memory synchronization .

多线程编程的难点在于每个线程都有自己的本地 CPU 内存缓存,然后与中央内存同步。正在读取的线程将看不到看到同步写入所做的更新。更糟糕的是,他们可能会看到 map 内存的部分更新,这会导致异常。

要同步您的 map ,您应该将其包装在 Collections.synchronizedMap(...) 调用中,或者(如 @SLaks 在评论中提到的那样),使用 ConcurrentHashMap它是为多个读者/作者构建的。 @SLaks 还提到了 ReaderWriterLock,但 CHM 会更高效,并且需要维护的代码也会少得多。

更具体地说,在“阻塞”方面,CHM 对映射进行分区,并以最小的阻塞处理多个读取器和写入器,做得非常出色。例如,从 CHM 获取实际上执行锁定的唯一时间是查找在 get 调用之前立即插入到映射中的对象时。

我不会担心 CHM 的性能,除非探查器告诉您这是一个性能问题。

关于java - 如何在允许同时读取线程的同时同步 HashMap?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19505761/

相关文章:

java - JSP页面如何在同一个表中列出两个不同的bean?

java - 任何知道应用程序 ID 的人都可以部署到 GAE 吗?

java - 屏幕旋转导致文字颜色变化

c# - 如何使用线程或计时器从 WPF 客户端应用程序定期执行方法

javascript - HTML5 Webworkers - 所有一个文件

c++ - 寻找对我的读者/作家实现的批评

ruby - JRuby 多核处理用法

java - 为什么 Java 不提示模棱两可的调用?

Java:打印数组元素

java - 仅在异步任务完成后才需要运行任务