Skip to content

Commit 646fd3e

Browse files
committed
Avoid thread pinning in SseEmitter write operations
This commit changes the `synchronized` usage into a `ReentrantLock`, in order to guard write operations with a construct that does not pin virtual threads to the current platform thread on JDK21. Closes gh-30996
1 parent 9908967 commit 646fd3e

File tree

1 file changed

+13
-1
lines changed
  • spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation

1 file changed

+13
-1
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/SseEmitter.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import java.util.Collections;
2222
import java.util.LinkedHashSet;
2323
import java.util.Set;
24+
import java.util.concurrent.locks.Lock;
25+
import java.util.concurrent.locks.ReentrantLock;
2426

2527
import org.springframework.http.HttpHeaders;
2628
import org.springframework.http.MediaType;
@@ -36,12 +38,18 @@
3638
* @author Rossen Stoyanchev
3739
* @author Juergen Hoeller
3840
* @author Sam Brannen
41+
* @author Brian Clozel
3942
* @since 4.2
4043
*/
4144
public class SseEmitter extends ResponseBodyEmitter {
4245

4346
private static final MediaType TEXT_PLAIN = new MediaType("text", "plain", StandardCharsets.UTF_8);
4447

48+
/**
49+
* Guards access to write operations on the response.
50+
*/
51+
private final Lock writeLock = new ReentrantLock();
52+
4553
/**
4654
* Create a new SseEmitter instance.
4755
*/
@@ -122,9 +130,13 @@ public void send(Object object, @Nullable MediaType mediaType) throws IOExceptio
122130
*/
123131
public void send(SseEventBuilder builder) throws IOException {
124132
Set<DataWithMediaType> dataToSend = builder.build();
125-
synchronized (this) {
133+
this.writeLock.lock();
134+
try {
126135
super.send(dataToSend);
127136
}
137+
finally {
138+
this.writeLock.unlock();
139+
}
128140
}
129141

130142
@Override

0 commit comments

Comments
 (0)