java Volatile HashMap 与 ConcurrentHashMap
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10357823/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Volatile HashMap vs ConcurrentHashMap
提问by DarthVader
I have a cache class which contains a volatile HashMap<T>
to store cache items.
我有一个缓存类,其中包含一个volatile HashMap<T>
用于存储缓存项的缓存类。
I'm curious what would be the consequences of changing volatile HashMap
to ConcurrentHashMap
?
我很好奇,这将是改变的后果volatile HashMap
来ConcurrentHashMap
?
Would i gain performance increase? This cache is readonly cache.
我会获得性能提升吗?这个缓存是只读缓存。
What would be the best option to use? just HashMap? Cache is being populated on a interval.
什么是最好的选择?只是HashMap?缓存按时间间隔填充。
回答by Brian Roach
First, it appears you don't understand what the volatile
keyword does. It makes sure that if the reference valueheld by the variable declared volatile
changes, other threads will see it rather than having a cached copy. It has nothing to do with thread-safety in regard to accessing the HashMap
首先,您似乎不了解volatile
关键字的作用。它确保如果声明的变量所持有的引用值volatile
发生变化,其他线程将看到它而不是缓存副本。它与访问线程安全无关HashMap
Given that, and the fact that you say the HashMap
is read-only ... you certainly don't need to use anything that provides thread-safety including a ConcurrentHashMap
鉴于此,以及您说它HashMap
是只读的事实……您当然不需要使用任何提供线程安全的东西,包括ConcurrentHashMap
Edit to add:Your last edit you now say "The cache is being populated on a interval"
编辑添加:您的最后一次编辑现在说“缓存正在按时间间隔填充”
That's not read-only then, is it?
那不是只读的,是吗?
If you're going to have threads reading from it whileyou are writing (updating the existing HashMap) then you should use a ConcurrentHashMap
, yes.
如果您在编写(更新现有的 HashMap)时要让线程从中读取,那么您应该使用ConcurrentHashMap
,是的。
If you are populating an entirely new HashMap
then assigning it to the existing variable, then you use volatile
如果您要填充一个全新HashMap
的变量,然后将其分配给现有变量,那么您可以使用volatile
回答by Michael Krussel
You say the cache is read-only, but also being updated on an interval which seems contradictory.
你说缓存是只读的,但也在一个似乎矛盾的时间间隔内更新。
If the whole cache gets updated on an interval, I'd keep using the volatile. The volatile will make sure that the updated map is safely published.
如果整个缓存按时间间隔更新,我会继续使用 volatile。volatile 将确保更新的地图被安全发布。
public final class Cache
{
private volatile Map<?,?> cache;
private void mapUpdate() {
Map<?,?> newCache = new HashMap<>();
// populate the map
// update the reference with an immutable collection
cache = Collections.unmodifiableMap(newCache);
}
}
If the interval update is modifying the same cache, then you probably want to use a ConcurrentHashMap, or copy the map, update the copy, and update the reference.
如果间隔更新正在修改相同的缓存,那么您可能希望使用 ConcurrentHashMap,或者复制映射、更新副本和更新引用。
public final class Cache
{
private volatile Map<?,?> cache;
private void mapUpdate() {
Map<?,?> newCache = new HashMap<>(cache);
// update the map
// update the reference with an immutable collection
cache = Collections.unmodifiableMap(newCache);
}
}
回答by Ayaskant
I have a similar use case for my web application. I am using a HAshMap for my in-memory cache. The use case is as follows -
我的 Web 应用程序有一个类似的用例。我正在为我的内存缓存使用 HAshMap。用例如下 -
- One user request comes in and first checks the cache for existence of a record using an input key. This is done in the add method.
- If the object is not present then it inserts the new record in the cache.
- Similarly in the remove method first checks the presence of a record in the cache using the key and if found just removes that.
- 一个用户请求传入并首先使用输入键检查缓存是否存在记录。这是在 add 方法中完成的。
- 如果对象不存在,则它会在缓存中插入新记录。
- 同样,在 remove 方法中,首先使用键检查缓存中是否存在记录,如果找到则将其删除。
I want to make sure of two threads are concurrently executing one on add and another on remove method will this approach make sure they at point of them they see the latest data in the cache? If i am not wrong then synchronized method takes care of thread safety where as volatile takes care of visibility.
我想确保两个线程同时执行一个添加和另一个删除方法,这种方法是否可以确保他们在此时看到缓存中的最新数据?如果我没有错,那么同步方法负责线程安全,而 volatile 负责可见性。
private volatile HashMap<String,String> activeRequests = new HashMap<String,String>();
public synchronized boolean add(String pageKey, String space, String pageName) {
if (!(activeRequests.get(pageKey) == null)) {
return false;
}
activeRequests.put(pageKey, space + ":" + pageName);
return true;
}
public synchronized void remove(String pageKey) {
if(!(activeRequests.get(pageKey) == null))
activeRequests.remove(pageKey);
}