Skip to content

Commit f28bf61

Browse files
committed
Safely add and register the MessageListener to Topic mapping.
Given addListener(:MessageListener, :Collection<Topic>) could be called concurrently from the addMessageListener(:MessageListener, Collection<Topic>) method by multiple Threads, and the RedisMessageListenerContainer Javadoc specifically states that it is safe to call the addMessageListener(..) method conurrently without any external synchronization, and the registeration (or mapping) of listener to Topics is a componund action, then a race condition is possible. Closes #2755
1 parent fc9f9d8 commit f28bf61

File tree

1 file changed

+4
-9
lines changed

1 file changed

+4
-9
lines changed

src/main/java/org/springframework/data/redis/listener/RedisMessageListenerContainer.java

+4-9
Original file line numberDiff line numberDiff line change
@@ -639,19 +639,14 @@ private void initMapping(Map<? extends MessageListener, Collection<? extends Top
639639

640640
private void addListener(MessageListener listener, Collection<? extends Topic> topics) {
641641

642-
Assert.notNull(listener, "a valid listener is required");
643-
Assert.notEmpty(topics, "at least one topic is required");
642+
Assert.notNull(listener, "A valid listener is required");
643+
Assert.notEmpty(topics, "At least one topic is required");
644644

645645
List<byte[]> channels = new ArrayList<>(topics.size());
646646
List<byte[]> patterns = new ArrayList<>(topics.size());
647647

648-
// add listener mapping
649-
Set<Topic> set = listenerTopics.get(listener);
650-
651-
if (set == null) {
652-
set = new CopyOnWriteArraySet<>();
653-
listenerTopics.put(listener, set);
654-
}
648+
// safely lookup or add MessageListener to Topic mapping
649+
Set<Topic> set = listenerTopics.computeIfAbsent(listener, key -> new CopyOnWriteArraySet<>());
655650

656651
set.addAll(topics);
657652

0 commit comments

Comments
 (0)