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

  • A+
Category:Languages

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;         }     } 

 


Your confusing two different terms.
ConcurrentHashMap prevents corruption of internal structure, but doesn't prevent race conditions. If all you want to avoid is data corruption, then use of ConcurrentHashMap is valid.
But from your question it seems that you're trying to avoid race conditions. ConcurrentHashMap doesn't protect you from them in any way.

To understand it better, let's see the following example:

    Map<String, POJO> map = new ConcurrentHashMap<>();     ExecutorService pool = Executors.newWorkStealingPool(10);      for (int t = 0; t < 10; t++) {         pool.execute(() -> {             for (int i = 0; i < 100_000; i++) {                 map.compute("A", (k, v) -> {                     if (v == null) {                         return new POJO();                     }                     v.a = ++v.a;                     v.b = ++v.b;                      return v;                 });             }         });     }      pool.awaitTermination(5, TimeUnit.SECONDS);      System.out.println(map);      // With POJO like      class POJO {        // toString() here        Integer a = 1;        Integer b = 1;     } 

Here we get {A=POJO{a=1000000, b=1000000}}, so our operation was thread safe. If that's all you want you get, you're fine.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: