我正在使用以下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/