Atomically incrementing counters stored in ConcurrentHashMap
In Java 8: ConcurrentHashMap<String, LongAdder> map = new ConcurrentHashMap<>(); map.computeIfAbsent(“key”, k -> new LongAdder()).increment();
In Java 8: ConcurrentHashMap<String, LongAdder> map = new ConcurrentHashMap<>(); map.computeIfAbsent(“key”, k -> new LongAdder()).increment();
Java 8 introduced an API to cater for this exact problem, making a 1-line solution: public void record(String key, String value) { entries.computeIfAbsent(key, k -> Collections.synchronizedList(new ArrayList<String>())).add(value); } For Java 7: public void record(String key, String value) { List<String> values = entries.get(key); if (values == null) { entries.putIfAbsent(key, Collections.synchronizedList(new ArrayList<String>())); // At this point, there … Read more
I guess this depends on your use case, but why would you need a CopyOnWriteMap when you already have a ConcurrentHashMap? For a plain lookup table with many readers and only one or few updates it is a good fit. Compared to a copy on write collection: Read concurrency: Equal to a copy on write … Read more
No, you are losing the benefits of ConcurrentHashMap by doing that. You may as well be using a HashMap with synchronized or synchronizedMap() to lock the whole table (which is what you do when wrapping operations in synchronized, since the monitor implied is the entire object instance.) The purpose of ConcurrentHashMap is to increase the … Read more
casTabAt(tab, i, null, r) is publishing the reference to r. static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i, Node<K,V> c, Node<K,V> v) { return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v); } Because c is being put into tab, it is possible that it is accessed by another thread, e.g. in putVal. As such, … Read more
The point is to provide an implementation of HashMap that is threadsafe. Multiple threads can read from and write to it without the chance of receiving out-of-date or corrupted data. ConcurrentHashMap provides its own synchronization, so you do not have to synchronize accesses to it explicitly. Another feature of ConcurrentHashMap is that it provides the … Read more
Concurrency is hard. If you are going to bother with concurrent maps instead of straightforward locking, you might as well go for it. Indeed, don’t do lookups more than necessary. Set<X> set = map.get(name); if (set == null) { final Set<X> value = new HashSet<X>(); set = map.putIfAbsent(name, value); if (set == null) { set … Read more
This is of course a “feature”. The ConcurrentHashMap.computeIfAbsent() Javadoc reads: If the specified key is not already associated with a value, attempts to compute its value using the given mapping function and enters it into this map unless null. The entire method invocation is performed atomically, so the function is applied at most once per … Read more
These two classes vary in a few ways. ConcurrentHashMap does not guarantee* the runtime of its operations as part of its contract. It also allows tuning for certain load factors (roughly, the number of threads concurrently modifying it). ConcurrentSkipListMap, on the other hand, guarantees average O(log(n)) performance on a wide variety of operations. It also … Read more
I found the reason: it is a Problem of gcc-4.7!! With gcc-4.7 inserts: 37728 get : 2985 With gcc-4.6 inserts: 2531 get : 1565 So std::unordered_map in gcc-4.7 is broken (or my installation, which is an installation of gcc-4.7.0 on Ubuntu – and another installation which is gcc 4.7.1 on debian testing). I will submit … Read more