@@ -497,7 +497,7 @@ private Class<?> getCustomTarget(Class<?> sourceType, @Nullable Class<?> targetT
497497 */
498498 static class ConversionTargetsCache {
499499
500- private Map <Class <?>, TargetTypes > customReadTargetTypes = new HashMap <>();
500+ private volatile Map <Class <?>, TargetTypes > customReadTargetTypes = new HashMap <>();
501501
502502 /**
503503 * Get or compute a target type given its {@code sourceType}. Returns a cached {@link Optional} if the value
@@ -531,10 +531,19 @@ public Class<?> computeIfAbsent(Class<?> sourceType, Class<?> targetType,
531531
532532 if (targetTypes == null ) {
533533
534- Map <Class <?>, TargetTypes > customReadTargetTypes = new HashMap <>(this .customReadTargetTypes );
535- targetTypes = new TargetTypes (sourceType );
536- customReadTargetTypes .put (sourceType , targetTypes );
537- this .customReadTargetTypes = customReadTargetTypes ;
534+ synchronized (this ) {
535+
536+ TargetTypes customReadTarget = customReadTargetTypes .get (sourceType );
537+ if (customReadTarget != null ) {
538+ targetTypes = customReadTarget ;
539+ } else {
540+
541+ Map <Class <?>, TargetTypes > customReadTargetTypes = new HashMap <>(this .customReadTargetTypes );
542+ targetTypes = new TargetTypes (sourceType );
543+ customReadTargetTypes .put (sourceType , targetTypes );
544+ this .customReadTargetTypes = customReadTargetTypes ;
545+ }
546+ }
538547 }
539548
540549 return targetTypes .computeIfAbsent (targetType , mappingFunction );
@@ -554,7 +563,7 @@ interface AbsentTargetTypeMarker {}
554563 static class TargetTypes {
555564
556565 private final Class <?> sourceType ;
557- private Map <Class <?>, Class <?>> conversionTargets = new HashMap <>();
566+ private volatile Map <Class <?>, Class <?>> conversionTargets = new HashMap <>();
558567
559568 TargetTypes (Class <?> sourceType ) {
560569 this .sourceType = sourceType ;
@@ -576,11 +585,19 @@ public Class<?> computeIfAbsent(Class<?> targetType, Function<ConvertiblePair, C
576585
577586 if (optionalTarget == null ) {
578587
579- optionalTarget = mappingFunction .apply (new ConvertiblePair (sourceType , targetType ));
588+ synchronized (this ) {
589+
590+ Class <?> conversionTarget = conversionTargets .get (targetType );
591+ if (conversionTarget != null ) {
592+ optionalTarget = conversionTarget ;
593+ } else {
580594
581- Map <Class <?>, Class <?>> conversionTargets = new HashMap <>(this .conversionTargets );
582- conversionTargets .put (targetType , optionalTarget == null ? Void .class : optionalTarget );
583- this .conversionTargets = conversionTargets ;
595+ optionalTarget = mappingFunction .apply (new ConvertiblePair (sourceType , targetType ));
596+ Map <Class <?>, Class <?>> conversionTargets = new HashMap <>(this .conversionTargets );
597+ conversionTargets .put (targetType , optionalTarget == null ? Void .class : optionalTarget );
598+ this .conversionTargets = conversionTargets ;
599+ }
600+ }
584601 }
585602
586603 return Void .class .equals (optionalTarget ) ? null : optionalTarget ;
0 commit comments