spring-projects / spring-data-redis

Provides support to increase developer productivity in Java when using Redis, a key-value store. Uses familiar Spring concepts such as a template classes for core API usage and lightweight repository style data access.
https://spring.io/projects/spring-data-redis/
Apache License 2.0
1.75k stars 1.16k forks source link

Revisit `synchronized` blocks involving blocking operations #2690

Closed giger85 closed 1 year ago

giger85 commented 1 year ago

Version

Issue

Detects virtual thread parking & pinning when LettuceConnectionFactory.getSharedConnection() is called. Stack trace is below. (need to be apply -Djdk.tracePinnedThreads=full)

Thread[#116,ForkJoinPool-1-worker-2,5,CarrierThreads]
    java.base/java.lang.VirtualThread$VThreadContinuation.onPinned(VirtualThread.java:185)
    java.base/jdk.internal.vm.Continuation.onPinned0(Continuation.java:393)
    java.base/java.lang.VirtualThread.park(VirtualThread.java:592)
    java.base/java.lang.System$2.parkVirtualThread(System.java:2639)
    java.base/jdk.internal.misc.VirtualThreads.park(VirtualThreads.java:54)
    java.base/java.util.concurrent.locks.LockSupport.park(LockSupport.java:219)
    java.base/java.util.concurrent.CompletableFuture$Signaller.block(CompletableFuture.java:1864)
    java.base/java.util.concurrent.ForkJoinPool.unmanagedBlock(ForkJoinPool.java:3780)
    java.base/java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3725)
    java.base/java.util.concurrent.CompletableFuture.waitingGet(CompletableFuture.java:1898)
    java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2072)
    io.lettuce.core.DefaultConnectionFuture.get(DefaultConnectionFuture.java:69)
    io.lettuce.core.AbstractRedisClient.getConnection(AbstractRedisClient.java:345)
    io.lettuce.core.RedisClient.connect(RedisClient.java:216)
    org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.lambda$getConnection$1(StandaloneConnectionProvider.java:112)
    java.base/java.util.Optional.orElseGet(Optional.java:364)
    org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.getConnection(StandaloneConnectionProvider.java:112)
    org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1626)
    org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getNativeConnection(LettuceConnectionFactory.java:1453)
    org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getConnection(LettuceConnectionFactory.java:1436) <== monitors:1
    org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getSharedConnection(LettuceConnectionFactory.java:1127)
    org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getConnection(LettuceConnectionFactory.java:465)
...

Do you have any plan that avoid thread pinning? (ex. Use ReentrantLock)

mp911de commented 1 year ago

Thanks a lot for letting us know. It makes indeed sense to revisit our synchronized blocks to avoid platform thread pinning.

giger85 commented 1 year ago

@mp911de Thanks for your reply. I will wait next milestone version. (It might be 3.2 M3)