diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/SseEmitter.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/SseEmitter.java index 5067f5b71987..836e1d2b2332 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/SseEmitter.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/SseEmitter.java @@ -21,6 +21,8 @@ import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; @@ -36,12 +38,18 @@ * @author Rossen Stoyanchev * @author Juergen Hoeller * @author Sam Brannen + * @author Brian Clozel * @since 4.2 */ public class SseEmitter extends ResponseBodyEmitter { private static final MediaType TEXT_PLAIN = new MediaType("text", "plain", StandardCharsets.UTF_8); + /** + * Guards access to write operations on the response. + */ + private final Lock writeLock = new ReentrantLock(); + /** * Create a new SseEmitter instance. */ @@ -122,9 +130,13 @@ public void send(Object object, @Nullable MediaType mediaType) throws IOExceptio */ public void send(SseEventBuilder builder) throws IOException { Set dataToSend = builder.build(); - synchronized (this) { + this.writeLock.lock(); + try { super.send(dataToSend); } + finally { + this.writeLock.unlock(); + } } @Override