diff --git serde/src/java/org/apache/hadoop/hive/serde2/avro/InstanceCache.java serde/src/java/org/apache/hadoop/hive/serde2/avro/InstanceCache.java index 2d52020915..9478ec7fc2 100644 --- serde/src/java/org/apache/hadoop/hive/serde2/avro/InstanceCache.java +++ serde/src/java/org/apache/hadoop/hive/serde2/avro/InstanceCache.java @@ -17,7 +17,7 @@ */ package org.apache.hadoop.hive.serde2.avro; -import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; import java.util.Map; import java.util.Set; @@ -35,7 +35,7 @@ */ public abstract class InstanceCache { private static final Logger LOG = LoggerFactory.getLogger(InstanceCache.class); - Map cache = new HashMap(); + Map cache = new ConcurrentHashMap(); public InstanceCache() {} @@ -51,19 +51,24 @@ public Instance retrieve(SeedObject hv) throws AvroSerdeException { * Retrieve (or create if it doesn't exist) the correct Instance for this * SeedObject using 'seenSchemas' to resolve circular references */ - public synchronized Instance retrieve(SeedObject hv, - Set seenSchemas) throws AvroSerdeException { + public Instance retrieve(SeedObject hv, Set seenSchemas) + throws AvroSerdeException { if(LOG.isDebugEnabled()) LOG.debug("Checking for hv: " + hv.toString()); - if(cache.containsKey(hv)) { + // Ideally, we should use ConcurrentHashMap's computeIfAbsent. While computeIfAbsent + // is only available on java 8 and java 7 is still supported in Hive, + // we use the following pattern to simulate the behavior of computeIfAbsent. + // In the future, we should move to computeIfAbsent when Hive requires java 8. + Instance instance = cache.get(hv); + + if(instance != null) { if(LOG.isDebugEnabled()) LOG.debug("Returning cache result."); - return cache.get(hv); + } else { + if(LOG.isDebugEnabled()) LOG.debug("Creating new instance and storing in cache"); + Instance newInstance = makeInstance(hv, seenSchemas); + instance = (instance = cache.putIfAbsent(hv, newInstance)) == null ? + newInstance : instance; } - - if(LOG.isDebugEnabled()) LOG.debug("Creating new instance and storing in cache"); - - Instance instance = makeInstance(hv, seenSchemas); - cache.put(hv, instance); return instance; }