Skip to content

Commit 1fd8cb1

Browse files
authored
InternCache - remove synchronized (#1251)
1 parent 695ca3f commit 1fd8cb1

File tree

2 files changed

+18
-7
lines changed

2 files changed

+18
-7
lines changed

release-notes/VERSION-2.x

+4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ a pure JSON library.
1616

1717
2.18.0 (not yet released)
1818

19+
#1251: `InternCache` replace synchronized with `ReentrantLock` - the cache
20+
size limit is no longer strictly enforced for performance reasons but
21+
we should never go far about the limit
22+
(contributed by @pjfanning)
1923
#1252: `ThreadLocalBufferManager` replace synchronized with `ReentrantLock`
2024
(contributed by @pjfanning)
2125

src/main/java/com/fasterxml/jackson/core/util/InternCache.java

+14-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.fasterxml.jackson.core.util;
22

33
import java.util.concurrent.ConcurrentHashMap;
4+
import java.util.concurrent.locks.ReentrantLock;
45

56
/**
67
* Singleton class that adds a simple first-level cache in front of
@@ -29,7 +30,7 @@ public final class InternCache
2930
* cases where multiple threads might try to concurrently
3031
* flush the map.
3132
*/
32-
private final Object lock = new Object();
33+
private final ReentrantLock lock = new ReentrantLock();
3334

3435
public InternCache() { this(MAX_ENTRIES, 0.8f, 4); }
3536

@@ -47,13 +48,19 @@ public String intern(String input) {
4748
* we are simply likely to keep on clearing same, commonly used entries.
4849
*/
4950
if (size() >= MAX_ENTRIES) {
50-
/* Not incorrect wrt well-known double-locking anti-pattern because underlying
51-
* storage gives close enough answer to real one here; and we are
52-
* more concerned with flooding than starvation.
51+
/* As of 2.18, the limit is not strictly enforced, but we do try to
52+
* clear entries if we have reached the limit. We do not expect to
53+
* go too much over the limit, and if we do, it's not a huge problem.
54+
* If some other thread has the lock, we will not clear but the lock should
55+
* not be held for long, so another thread should be able to clear in the near future.
5356
*/
54-
synchronized (lock) {
55-
if (size() >= MAX_ENTRIES) {
56-
clear();
57+
if (lock.tryLock()) {
58+
try {
59+
if (size() >= MAX_ENTRIES) {
60+
clear();
61+
}
62+
} finally {
63+
lock.unlock();
5764
}
5865
}
5966
}

0 commit comments

Comments
 (0)