-
Notifications
You must be signed in to change notification settings - Fork 41.5k
Description
Good afternoon.
I'd like to discuss the potential issue of enabling virtual threads at the platform level. I would update spring's documentation to use virtual threads. I would highlight this feature in red and warn other developers about possible problems. Virtual threads can be a very big problem if used incorrectly.
spring.threads.virtual.enabled: true
- creates a strong temptation to install immediately and everywhere.
This property makes us think that the entire spring will work correctly with virtual threads. But this is definitely not the case.
Let's say I want to use spring-boot-starter-mail
... I start sending a message in a virtual thread.
So what do I see? If I check the application with Flight Recorder I see a lot of jdk.VirtualThreadPinned
events. If you look at the source code, this is an anti-pattern for virtual threads. There is synchronized
inside and data is sent via the socket inside.
I sent messages 3 times and received 59 VirtualThreadPinned. Subject to triggering 20 ms, pinned time was from 100 to 900 ms...
Due to such limitations of virtual threads, you need to be extremely careful when using. Otherwise it can be fatal for the application.
Quote from Quarkus:
Monopolization cases
When running long computations, we do not allow the JVM to unmount and switch to another virtual thread until the virtual thread terminates. Indeed, the current scheduler does not support preempting tasks.This monopolization can lead to the creation of new carrier threads to execute other virtual threads. Creating carrier threads results in creating platform threads. So, there is a memory cost associated with this creation.
Suppose you run in a constrained environment, such as containers. In that case, monopolization can quickly become a concern, as the high memory usage can lead to out-of-memory issues and container termination. The memory usage may be higher than with regular worker threads because of the inherent cost of the scheduling and virtual threads.
Pinning cases
The promise of "cheap blocking" might not always hold: a virtual thread might pin its carrier on certain occasions. The platform thread is blocked in this situation, precisely as it would have been in a typical blocking scenario.According to JEP 425 this can happen in two situations:
when a virtual thread performs a blocking operation inside a synchronized block or method
when it executes a blocking operation inside a native method or a foreign function
Before introducing virtual threads, you need to check the entire application in detail. The current state of java projects does not allow them to be used thoughtlessly. Not even all JDK classes can handle virtual threads - look at the class jdk.internal.misc.Blocker
.
I see a lot of advertisements for virtual threads... Some may think that this is the solution to their problems. But virtual threads can be a problem. We need to talk about possible problems at every step.
Spring lacks the ability to fine-tune launch control in virtual threads. For example, you can enter an annotation like Quarkus - @RunOnVirtualThread
. And it is also possible to add an annotation by analogy @ThreadSafe, @NotThreadSafe
- @VirtualThreadSafe, @NotVirtualThreadSafe
. In terms of severity I would equate it to thread safety.
The current java world is not fully prepared for virtual threads. They can create many more problems. But excessive advertising only makes the situation worse.
It is necessary to update the documentation and warn users very strongly about the risks that they can create for themselves and their systems.
P.S. I can pay a lot of attention to this. I can pay a lot of attention to this, but I'm worried about this new and dangerous opportunity. It should be used very carefully