From e932c9453be7b36e8874fe92edb3710beef4e47c Mon Sep 17 00:00:00 2001 From: Ashley Taylor <7232476+ashley-taylor@users.noreply.github.com> Date: Sat, 1 Jun 2024 03:52:55 +1200 Subject: [PATCH] AVRO-3987 replace synchronized with immutable replacement approach (#2900) --- .../main/java/org/apache/avro/reflect/ReflectData.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java b/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java index 347490679ee..24173b9b273 100644 --- a/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java +++ b/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java @@ -360,8 +360,8 @@ protected ClassAccessorData computeValue(Class c) { static class ClassAccessorData { private final Class clazz; private final Map byName = new HashMap<>(); - // getAccessorsFor is already synchronized, no need to wrap - final Map bySchema = new WeakHashMap<>(); + // getAccessorsFor replaces this map with each modification + volatile Map bySchema = new WeakHashMap<>(); private ClassAccessorData(Class c) { clazz = c; @@ -379,12 +379,14 @@ private ClassAccessorData(Class c) { * Return the field accessors as an array, indexed by the field index of the * given schema. */ - private synchronized FieldAccessor[] getAccessorsFor(Schema schema) { - // if synchronized is removed from this method, adjust bySchema appropriately + private FieldAccessor[] getAccessorsFor(Schema schema) { + // to avoid synchronization, we replace the map for each modification FieldAccessor[] result = bySchema.get(schema); if (result == null) { result = createAccessorsFor(schema); + Map bySchema = new WeakHashMap<>(this.bySchema); bySchema.put(schema, result); + this.bySchema = bySchema; } return result; }