Skip to content

Commit a0ddc0e

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 5778dec commit a0ddc0e

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
@@ -645,19 +645,14 @@ private void initMapping(Map<? extends MessageListener, Collection<? extends Top
645645

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

648-
Assert.notNull(listener, "a valid listener is required");
649-
Assert.notEmpty(topics, "at least one topic is required");
648+
Assert.notNull(listener, "A valid listener is required");
649+
Assert.notEmpty(topics, "At least one topic is required");
650650

651651
List<byte[]> channels = new ArrayList<>(topics.size());
652652
List<byte[]> patterns = new ArrayList<>(topics.size());
653653

654-
// add listener mapping
655-
Set<Topic> set = listenerTopics.get(listener);
656-
657-
if (set == null) {
658-
set = new CopyOnWriteArraySet<>();
659-
listenerTopics.put(listener, set);
660-
}
654+
// safely lookup or add MessageListener to Topic mapping
655+
Set<Topic> set = listenerTopics.computeIfAbsent(listener, key -> new CopyOnWriteArraySet<>());
661656

662657
set.addAll(topics);
663658

0 commit comments

Comments
 (0)