1
1
package com .fasterxml .jackson .databind .deser ;
2
2
3
3
import java .util .HashMap ;
4
+ import java .util .concurrent .locks .ReentrantLock ;
4
5
5
6
import com .fasterxml .jackson .annotation .JsonFormat ;
6
7
import com .fasterxml .jackson .databind .*;
@@ -52,6 +53,15 @@ public final class DeserializerCache
52
53
protected final HashMap <JavaType , JsonDeserializer <Object >> _incompleteDeserializers
53
54
= new HashMap <JavaType , JsonDeserializer <Object >>(8 );
54
55
56
+
57
+ /**
58
+ * We hold an explicit lock while creating deserializers to avoid creating duplicates.
59
+ * Guards {@link #_incompleteDeserializers}.
60
+ *
61
+ * @since 2.17
62
+ */
63
+ private final ReentrantLock _incompleteDeserializersLock = new ReentrantLock ();
64
+
55
65
/*
56
66
/**********************************************************
57
67
/* Life-cycle
@@ -162,10 +172,9 @@ public JsonDeserializer<Object> findValueDeserializer(DeserializationContext ctx
162
172
// If not, need to request factory to construct (or recycle)
163
173
deser = _createAndCacheValueDeserializer (ctxt , factory , propertyType );
164
174
if (deser == null ) {
165
- /* Should we let caller handle it? Let's have a helper method
166
- * decide it; can throw an exception, or return a valid
167
- * deserializer
168
- */
175
+ // Should we let caller handle it? Let's have a helper method
176
+ // decide it; can throw an exception, or return a valid
177
+ // deserializer
169
178
deser = _handleUnknownValueDeserializer (ctxt , propertyType );
170
179
}
171
180
}
@@ -204,9 +213,8 @@ public boolean hasValueDeserializerFor(DeserializationContext ctxt,
204
213
DeserializerFactory factory , JavaType type )
205
214
throws JsonMappingException
206
215
{
207
- /* Note: mostly copied from findValueDeserializer, except for
208
- * handling of unknown types
209
- */
216
+ // Note: mostly copied from findValueDeserializer, except for
217
+ // handling of unknown types
210
218
JsonDeserializer <Object > deser = _findCachedDeserializer (type );
211
219
if (deser == null ) {
212
220
deser = _createAndCacheValueDeserializer (ctxt , factory , type );
@@ -245,7 +253,8 @@ protected JsonDeserializer<Object> _createAndCacheValueDeserializer(Deserializat
245
253
// Only one thread to construct deserializers at any given point in time;
246
254
// limitations necessary to ensure that only completely initialized ones
247
255
// are visible and used.
248
- synchronized (_incompleteDeserializers ) {
256
+ _incompleteDeserializersLock .lock ();
257
+ try {
249
258
// Ok, then: could it be that due to a race condition, deserializer can now be found?
250
259
JsonDeserializer <Object > deser = _findCachedDeserializer (type );
251
260
if (deser != null ) {
@@ -268,6 +277,8 @@ protected JsonDeserializer<Object> _createAndCacheValueDeserializer(Deserializat
268
277
_incompleteDeserializers .clear ();
269
278
}
270
279
}
280
+ } finally {
281
+ _incompleteDeserializersLock .unlock ();
271
282
}
272
283
}
273
284
0 commit comments