My understanding is there is work to make synchronized not pin the carrier thread, but that's some pretty complex and important code to change.
My understanding is there is work to make synchronized not pin the carrier thread, but that's some pretty complex and important code to change.
It definitely leaves room to optimize by not pinning that thread, which would be great, but that shouldn't change semantics at all. Or is there something actually screwed up in the implementation of virtual threads that makes this a much bigger issue?
Been away from Java land for a while. How did something like that even get into release? That’s like a pretty big loaded shotgun to leave lying around with lots of kids playing, no?
Also, this is a benchmark. It's not surprising that they managed to produce a situation where more than n_cores virtual threads would actually start waiting.
So I don’t see the big fuss about it - don’t spawn a million virtual thread that all just spams synchronized?
If they're, like, limiting to CPU cores * 2 threads: yeah that would be Bad™. Unambiguously. I haven't been able to find anything conclusive about this though.
As mentioned in another comment: jdk.virtualThreadScheduler.maxPoolSize
That would indeed be a problem if it's not similarly unlimited by default. Configurable makes perfect sense, as does attempting to be conservative, but small hard-capped defaults are very obviously going to cause problems, especially while synchronized locks the carrier.
>The maximum number of platform threads available to the scheduler. It defaults to 256.
Yeah, that's pretty small. >256 simultaneous synchronized calls doesn't seem particularly extreme, given how common its use is.
Tho now I wonder if you can just set this to max-int and resume like normal, or if giant values do awful things internally...
The issue is that Object.wait doesn't suspend virtual threads, so you get deadlocks. The answer is to reimplement usages of the wait/notify pattern to use locks or concurrent collections (for example, using a concurrent message queue for the producer/consumer pattern, which is a common use case for synchronized/wait/notify).