Is it thread safe to modify a concurrentHashMap of values ArrayList?
If not , what is the most efficient way to initialize and update an arraylist of ints inside a ConcurrentHashMap?
Thanks
There are two data structures that need thread-safety in your example.
One is the map, so any updates on the map need to be thread-safe which you have gotten covered.
Second one is the arrayList. You need to ask what is the expected behavior if multiple threads are looking to update the same arrayList. Arraylists throw ConcurrentModificationException in such a scenario which you wouldn't want.
You should put in Collections.synchronizedList or CopyOnWriteArrayList in the map in such a case. The latter is a better alternative if there aren't too many updates.
Related
I have two thread that shares a common HashMap, one thread will always insert an objects to the Map and the second thread will remove objects from the HashMap.
my question is if this is the only logic of the two thread should I "protect" the Map with synchronize or ConcurrentHashMap, could I have a race condition?
if yes can you please explain what is the risk of not protecting the Map.
thanks
could I have a race condition
Yes, without synchronization or ConcurrentHashMap.
It is clearly stated in the Javadoc of HashMap:
Note that this implementation is not synchronized. If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally.
You have two threads modifying the map structurally, so you need to synchronize if you use HashMap.
please explain what is the risk of not protecting the Map
Undefined behavior, ranging from doing completely the wrong thing (the very best kind of undefined behavior, because you know it needs fixing), down to seeming to work, until you change your JVM version and it mysteriously stops working (the very worst kind of undefined behavior).
[Question]: Is it thread safe to use ConcurrentHashMap<Object, ConcurrentHashMap<Object, Object>> or not.
[Optional to answer]: Also what about another concurrent maps types? And what about concurrent collections?
P.S. I'm asking only about java.util.concurrent package.
Specific Usage Context:
//we have
ConcurrentHashMap<Object, ConcurrentHashMap<Object, Object>> map = new ConcurrentHashMap<Object, ConcurrentHashMap<Object, Object>>();
//each string can be executed separately and concurently
ConcurrentHashMap<Object, Object> subMap = new ConcurrentHashMap<Object, Object>()
map.put(key, subMap);
map.remove(key);
map.get(key);
map.get(key).put(key, ref);
map.get(key).remove(key);
Maybe my solution lays around Guava HashBasedTable?
You can't define thread safety without the specific context in which you plan to use your collections.
The concurrent collections you have named are thread-safe on their own in the sense that their internal invariants will not be broken by concurrent access; however that's just one bullet point on the thread safety checklist.
If you perform anything more than a single operation on your structure, which must be atomic as a whole, then you will not get thread safety just by using these classes. You will have to resort to classic locking, or some quite elaborate, and usually unmotivated, lock-free updating scheme.
Using the examples from your question, consider the following.
Thread 1 executes
map.get(mapKey).put(key, value);
At the same time, Thread 2 executes
map.remove(mapKey);
What is the outcome? Thread 1 may be putting something to a map which has already been removed, or it may even get a null result from get. In most cases more coordination will be needed for correctness.
Concurrent Collections means multiple thread could perform add/remove operation on collection same time, No it is not thread safe
More Detail:
for further please read
What's the difference between ConcurrentHashMap and Collections.synchronizedMap(Map)?
Is ConcurrentHashMap totally safe?
The concurrent collections are thread safe for reads; but you must expect ConcurrentModificationException in case of competing concurrent updates or when modifying a Collection while another thread is iterating over it.
this is what the javadoc of ConcurrentHashMap says:
However, even though all operations are thread-safe, retrieval operations do not entail locking, and there is not any support for locking the entire table in a way that prevents all access
So, they ARE thread-safe in terms of modifying it.
UPDATE
same javadoc http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html says:
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. For aggregate operations such as putAll and clear, concurrent retrievals may reflect insertion or removal of only some entries. Similarly, Iterators and Enumerations return elements reflecting the state of the hash table at some point at or since the creation of the iterator/enumeration. They do not throw ConcurrentModificationException. However, iterators are designed to be used by only one thread at a time.
In general the classes which are part of java.util.concurrent provide additional performance at the (potential) penalty of additional coding complexity.
The issue that I see with nesting ConcurrentMap instances is managing the populating the outer map with values at given keys. If all the keys are known upfront and values placed in the map in some sort of initialization phase, there are no issues (but you also likely would not need to have the outer map be a ConcurrentMap). If you need to be able to insert new maps into the outer map as you go, the work becomes a bit more complicated. When creating a new map to insert into the outer map, you would need to use the putIfAbsentmethod[1] and pay attention to the returned value to determine what instance to add data to.
[1] - http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentMap.html#putIfAbsent(K,%20V)
I wanted to use Collection for only single threaded environment and I am using a HashMap that is synchronized.
However, I still doubt if it is thread safe to have it synchronized or not.
If you're only using a single thread, you don't need a thread-safe collection - HashMap should be fine.
You should be very careful to work out your requirements:
If you're really using a single thread, stick with HashMap (or consider LinkedHashMap)
If you're sharing the map, you need to work out what kind of safety you want:
If the map is fully populated before it's used by multiple threads, which just read, then
HashMap is still fine.
Collections.synchronizedMap will only synchronize each individual operation; it still isn't
safe to iterate in one thread and modify the map in another thread without synchronization.
ConcurrentHashMap is a more "thoroughly" thread-safe approach, and one I'd generally prefer
over synchronizedMap. It allows for modification during iteration, but doesn't guarantee
where such modifications will be seen while iterating. Also note that while HashMap allows null
keys and values, ConcurrentHashMap doesn't.
For your needs, use ConcurrentHashMap. It allows concurrent modification of the Map from several threads without the need to block them. Collections.synchronizedMap(map) creates a blocking Map which will degrade performance, albeit ensure consistency
the standard java HashMap is not synchronized.
If you are in a single threaded environment you don't need to worry about synchronization.
The commonly used Collection classes, such as java.util.ArrayList, are not synchronized. However, if there's a chance that two threads could be altering a collection concurrently, you can generate a synchronized collection from it using the synchronizedCollection() method. Similar to the read-only methods, the thread-safe APIs let you generate a synchronized collection, list, set, or map. For instance, this is how you can generate a synchronized map from a HashMap:
Map map = Collections.synchronizedMap(new HashMap());
map.put(...
As its a single-threaded environment you can safely use HashMap.
I was recently writing a concurrent program in Java and came across the dollowing dilemma: suppose you have a global data structure, which is partof regular non-synchronized, non-concurrent lib such as HashMap. Is it OK to allow multiple threads to iterate through the collection (just reading, no modifications) perhaps at different, interleaved periods i.e. thread1 might be half way thrpugh iterating when thread2 gets his iterator on the same map?
It is OK. Ability to do this is the reason to create such interface as iterator. Every thread iterating over collection has its own instance of iterator that holds its state (e.g. where you are now in your iterating process).
This allows several threads to iterate over the same collection simultaneously.
It should be fine, as long as there are no writers.
This issue is similar to the readers-writer lock, where multiple readers are allowed to read from the data, but not during the time a writer "has" the lock for it. There is no concurrency issue for multiples read at the same time. [data race can occure only when you have at least one write].
Problems only arise when you attempt concurrent modifications on a data structure.
For instance, if one thread is iterating over the content of a Map, and another thread deletes elements from that collection, you'll be heading for serious trouble.
If you do need some threads to modify that collection safely, Java provides for mechanisms to do so, namely, ConcurrentHashMap.
ConcurrentHashMap in Java?
There is also Hashtable, which has the same interface as HashMap, but is synchronized, although it's use is not advised currently (deprecated), since it's performance suffers when the number of elements becomes larger (compared to ConcurrentHashMap which doesn't need to lock the entire Collection).
If you happen to have a Collection that is not synchronized and you need to have several threads reading and writing on top of it, you can use Collections.synchronizedMap(Map) to get a synchronized version of it.
The above answers are certainly good advice. In general, when writing Java with concurrent threads, so long as you do not modify a data structure, you need not worry about multiple threads concurrently reading that structure.
Should you have a similar problem in the future, except that the global data structure could be concurrently modified, I would suggest writing a Java class that all threads use to access and modify the structure. This class could impleement its own concurrency methodology, using either synchronized methods or locks. The Java tutorial has a very good explanation of Java's concurrency mechanisms. I have personally done this and it is fairly straight forward.
I need to use a HashMap of the form <String, ArrayList<String>> that is going to be
accessed by several different threads. From what I've managed to understand, ConcurrentHashMap is the preferred method. But will there be any problem with the fact that the value of the map is an ArrayList? Do I have to define the value as a synchronized ArrayList or something like that?
yes, there can be a problem. The ConcurrentHashMap will be thread safe for accesses into the Map, but the Lists served out need to be thread-safe, if multiple threads can operate on the same List instances concurrently.
So use a thread-safe list if that is true.
Edit -- now that i think about it, the rabbit-hole goes further. You have your Map, you have your List, and you have the objects in the list. Anything multiple threads can modify should be thread safe. So if many threads can modify the Map, Lists, and Objects in the Lists, then all of those should have thread-safety guards. If only the Map and List instances can be modified concurrently, only they need thread safety. If multiple threads can read everything, but not modify, then you don't need any thread safety (I think, someone will correct me if this is wrong)
ConcurrentHashMap guarantees atomicity in its mutating methods e.g. putIfAbsent, computeIfAbsent, computeIfPresent so if all the modification is done through these methods no problems will arise.
But at the same time, multiple threads can read the same map entry (concurrent reads are allowed). therefore multiple threads can access and modify an unsafe collection (map value)