Can we achieve read on mutable data after write atomically in ConcurrentHashMap in Java?

mitesh joshi :

I'm trying to find an answer to these, but not able to understand(or confirm) it on Google or in Java docs.

My implementation looks like as this:

Map<String, POJO> map = new ConcurrentHashMap<String, POJO>();

if I do

value1 = map.get(key1);
value1.setProp(prop);

Any other thread may override.

Now, I'm thinking if I do like follows: would it be an atomic operation/in another words, it will block the key1 segment?

map.compute(key1, (key1, value1) -> { value1.setProp(prop) });

Javadoc for compute function

Attempts to compute a mapping for the specified key and its current mapped value (or null if there is no current mapping). The entire method invocation is performed atomically. Some attempted update operations on this map by other threads may be blocked while computation is in progress, so the computation should be short and simple, and must not attempt to update any other mappings of this Map.

References:

1.https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html 2.https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html#compute-K-java.util.function.BiFunction-

EDIT:

for my final implementation, I did something like this as all threads share NewMap and at the end, I new list of POJOs
Abstract Data Type

    public class NewMap {

        private Map<String, POJO> map;
        private boolean isUpdatable;
        void NewMap(){
              isUpdatable = true;
              map = new ConcurrentHashMap();
        }

        void putPOJOProp1(String key, Type value) throws ReadOnlyException{

                  map.compute(key, (k,v) -> {
                           if(!isUpdatable) throw new ReadOnlyException();
                           if(k == null){ 
                              POJO p = new POJO();
                              p.setProp1(value);
                              v = p;
                           } else { 
                              v = v.setProp1(v)
                           }
             });
        }

        void putPOJOProp2....
        void putPOJOProp3....

        List<POJO> getAll() {
             isUpdatable = false;
             List<POJO> pojos;
             for(key: map.getKeys()) {
                  Pojo p = map.get(key);
                  p.setKey(key);
                  pojos.add(p);
             }
             return pojos;
        }
    }
Peter Lawrey :

The Javadoc for ConcurrentHashMap.compute states

The entire method invocation is performed atomically.

Note, by comparison the ConcurrentSkipListMap.compute is NOT atomic.

A more compact form of Alexey Soshin's answer is

Map<String, long[]> map = new ConcurrentSkipListMap<>();
map.put("A", new long[2]);
IntStream.range(0, 1_000_000)
        .parallel()
        .forEach(i -> map.compute("A", (k, v) -> {
            v[0]++;
            v[1]++;
            return v;
        }));
System.out.println(Arrays.toString(map.get("A")));

prints something like

[643553, 597254]

c.f. HashMap produces something like

[244786, 245993]

However, use a ConcurrentHashMap and you get the expected

[1000000, 1000000]

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=36327&siteId=1