Thread safe implementation for Hash Map
Asked Answered
L

5

5

First, I'll describe what I want and then I'll elaborate on the possibilities I am considering. I don't know which is the best so I want some help.

I have a hash map on which I do read and write operations from a Servlet. Now, since this Servlet is on Tomcat, I need the hash map to be thread safe. Basically, when it is being written to, nothing else should write to it and nothing should be able to read it as well.

I have seen ConcurrentHashMap but noticed its get method is not thread-safe. Then, I have seen locks and something called synchronized.

I want to know which is the most reliable way to do it.

Linea answered 1/8, 2013 at 16:55 Comment(6)
In what way is ConcurrentHashMap.get not threadsafe? And what level of granularity are you looking for? By "when it is being written to" do you mean that there will be multiple put operations, or is it sufficient for each one to be atomic?Grison
Seeing the API doc, I thought it is not thread safe. There can be multiple put operations to the hash map if say 3 people decide to do the same put operation.Linea
@Linea The fact that it allows concurrent operations does not make it not thread safe.Leucocytosis
Also, if something is being written to the hash map, somebody else shouldn't be able to read it. Does ConcurrentHashMap guarantee that?Linea
It does not guarantee that, from the javadoc: Retrieval operations (including get) generally do not block, so may overlap with update operations (including put and remove). Retrievals reflect the results of the most recently completed update operations holding upon their onset.Corticosteroid
I can't fathom what I was thinking and why I needed this specific condition (no reads or writes during a write) when I asked this. That too, for a class assignment. Don't use coarse grained locks, kids!Linea
S
4

EDIT: removed false information

In any case, the synchronized keyword is a safe bet. It blocks any threads from accessing the object while inside a synchronized block.

// Anything can modify map at this point, making it not thread safe
map.get(0);

as opposed to

// Nothing can modify map until the synchronized block is complete
synchronized(map) {
    map.get(0);
}
Surveyor answered 1/8, 2013 at 16:59 Comment(3)
There is only ever one instance of each Servlet in a container. All mapped requests will go through the same instance. If you have instance fields, then each request will have access to them.Fiance
Requests get executed in different threads i.e. service() method of servlets could get executed concurrently (unless Servlet is declared as SingleThreadModel) although there is a single instance of a servlet. Hence, instance variable declared in a Servlet class could be invoked from multiple request processing threads.Progenitive
Ack. You're (both) right, I don't know what I was thinking. I thought we (at work) had disproved this with a number of tests. I'll remove that part of my answer.Surveyor
D
19

ConcurrentHashMap.get() is thread safe.

You can make HashMap thread safe by wrapping it with Collections.synchronizedMap().

Dogmatism answered 1/8, 2013 at 16:57 Comment(2)
What's the difference?Microprint
@naXa ConcurrentHashMap allows concurrent access and a synchronized one doesn't.Dogmatism
S
4

EDIT: removed false information

In any case, the synchronized keyword is a safe bet. It blocks any threads from accessing the object while inside a synchronized block.

// Anything can modify map at this point, making it not thread safe
map.get(0);

as opposed to

// Nothing can modify map until the synchronized block is complete
synchronized(map) {
    map.get(0);
}
Surveyor answered 1/8, 2013 at 16:59 Comment(3)
There is only ever one instance of each Servlet in a container. All mapped requests will go through the same instance. If you have instance fields, then each request will have access to them.Fiance
Requests get executed in different threads i.e. service() method of servlets could get executed concurrently (unless Servlet is declared as SingleThreadModel) although there is a single instance of a servlet. Hence, instance variable declared in a Servlet class could be invoked from multiple request processing threads.Progenitive
Ack. You're (both) right, I don't know what I was thinking. I thought we (at work) had disproved this with a number of tests. I'll remove that part of my answer.Surveyor
H
3

Collections.synchronizedMap(new HashMap<K, V>);

Returns a synchronized (thread-safe) map backed by the specified map. In order to guarantee serial access, it is critical that all access to the backing map is accomplished through the returned map.

It is imperative that the user manually synchronize on the returned map when iterating over any of its collection views:

Horrorstruck answered 1/8, 2013 at 16:57 Comment(3)
What do you mean by "it is critical that all access to the backing sorted map is accomplished through the returned sorted map"?Linea
copied description of Collection.synchronizedSortedMap() by mistake, by that i meant that the map you passed in still would not be threadsafeHorrorstruck
I still don't understand the description.Linea
I
3

I would like to suggest you to go with ConcurrentHashMap , the requirement that you have mentioned above ,earlier I also had the same type of requirement for our application but we were little more focused on the performance side.

I ran both ConcurrentHashMap and map returned by Colecctions.synchronizedMap(); , under various types of load and launching multiple threads at a time using JMeter and I monitored them using JProfiler .After all these tests we came to conclusion that that map returned by Colecctions.synchronizedMap() was not as efficient in terms of performance in comaprison to ConcurrentHashMap.

I have written a post also on the same about my experience with both.

Thanks

Isosteric answered 1/8, 2013 at 17:9 Comment(0)
C
0

This is the point of ConcurrentHashMap class. It protects your collection, when you have more than 1 thread.

Charentemaritime answered 1/8, 2013 at 17:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.