Thanks everyone for their thoughts and opinions.
Let me clarify a few things:
- I’m not proposing removing 
asyncandawait. With virtual threads, I would hope they will fall out of fashion eventually, but I doubt they will ever be removed. - As proposed, virtual threads would be unable to support builtin functions in the call stack. I’m not opposed to adding support for that ability in the future, but the initial implementation would not support it. I will make sure that the design allows us to add it later if needed.
 - This is not an original idea and many languages have similar features, not just Java: goroutines in go and fibers in ruby were mentioned. I’m sure there are others. The reason I’m mentioning Java specifically is that virtual threads are integrated into the language and VM in such a way as to make the transition to them very smooth.
 - Context switching can only occur at well defined points in the program. But that is only if you are looking at the whole program. If you are looking at a single function only, then you will need to treat most calls are possible context switch points. There is no pre-emption.
 
Regarding true parallelism
Virtual threads are a means for single-threaded concurrency. However, for the pure Python version, they are normal Python objects and can be passed around like any other object. Combined with free-threading this would allow us to implement a NxM model where many virtual threads are run on a few operating system threads. This would, hypothetically, provide the utility of having thousands of threads with the low overhead of having only one or two OS threads per core.
If we add support for builtin functions (like greenlets) then those virtual threads would be pinned to a single OS thread.