Safely iterate an ConcurrentHashMap that is accessed by multiple thread
I have a ConcurrentHashMap object which is shared by multiple threads to access:
Map<String, MyConnection> myMap = new ConcurrentHashMap<String, MyConnection>();
The class MyConnection contains some connection to the datasource.
At a later stage, I need to iterate the ConcurrentHashMap, call MyConnection.close() method and remove it from the Map. Something like this:
for(String key : myMap.ketSet()) {
MyConnection connection = myMap.get(key);
connection.close();
myMap.remove(key);
}
However, the myMap is shared by multiple thread, which can be adding, removing from the ConcurrentHashMap at the same time.
How can I make sure the for loop above is thread safe to run? There is not requirement that the loop has to remove all the entries in the map. The loop only needs to remove all the elements at the time myMap.keySet() is called. Any subsequent elements added to the map does not have to be removed.
Obviously I can lock the entire for loop and prevents other thread from touching the map, but I think it is not performance efficient.
Can someone please share your opinion?
EDIT1 : And How about this? Is this thread safe?
for(MyConnection connection : myMap.values()) {
connection.close();
myMap.remove(connection.getId());
}
Each connection object has a ID, which is also the key of that entry.
Your method is currently not safe because your connection
could be null
(if another thread removes it while you are iterating), so a NullPointerException might be thrown. Simply add a null check and your method is correct and thread-safe.
If you're concerned with performance, you might want to simply iterate over map.values() and remove the variables that way, saving you two map lookups per iteration:
//the following code has not been compiled, and may be incorrect
Iterator<MyConnection> it = myMap.values().iterator();
while(it.hasNext())
{
MyConnection c = it.next();
if (c != null)
{
c.close();
}
it.remove();
}
Iterator/looping the way you presented are not thread safe in the sense that you're not iterating the most up-to-date map. But this is not your concern because you're simply removing an element from the hashmap - and that IS thread safe (due to ConcurrentHashMap). No need to put a lock or synchronized it makes no sense.
Both of your iteration are ok since your only removing it and you wrote:
The loop only needs to remove all the elements at the time myMap.keySet() is called.
Your code is just fine. You may need to check that your connection is not null before closing it (as suggested)
链接地址: http://www.djcxy.com/p/91920.html