Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Is this like .NET tasks? If so, what’s the async story here? Does it involve function colouring like in .NET?


The doco explains it quite well, so I won't repeat it here.

It's solving the same problem that async does, but it does it with virtual threads instead. The idea is that functions aren't coloured, and that normal threaded code will "just work".

I see some benefits of this approach, but I feel that what all of the solutions (Java, C#, Rust, etc...) are missing is structured concurrency[1], without which madness and eldritch horrors of late-night concurrent code debugging are guaranteed.

[1]: https://vorpus.org/blog/notes-on-structured-concurrency-or-g...


Project Loom will include structured concurrency. But most of that will come out in releases after virtual threads.

If you read the JEP though, you'll see that Executors are auto-closable now, which means you can use try-with-resources to wait for all spawned threads to stop before continuing execution.


In practice, I suspect structured concurrency will frequently requiring using the escape hatch for scenarios where a long lived background like task really is the right fit.

But the scape hatch works by.... coloring functions! Specifically if a function needs to spawn a longer lived background task, it needs to take a nursery parameter.

If a function wants to call a function that might spawn a long lived function, it needs to either own the lifetime of said nursery, or more commonly accept a nursery as a a parameter, and pass in the supplied one.

In practice with java, the nursery concept (StructuredExecutor) will only be used for those cases where it is actually helpful, (i.e. where you really want the function call to not return until all concurrent tasks are finished), and everywhere else, like background tasks, existing primitives will be used.

And all nurseries/StructuredExecutor is buying you is the ability structurally enforcing joining of the relevant virtual threads. It lets you avoid some of the common mistakes in structuring such code, but I'm not convinced that is where the eldritch horrors of concurrent code debugging live.

I think the real eldritch horrors come from buggy attempts to implement low lock code, failing to realize that locks or other synchronization is needed when accessing a certain variable, etc. Basically race condition type situations.

I personally almost never have had substantial concurrency issues related to failing to join my concurrent tasks.



In the "Alternatives" section of TFA there are some interesting comments regarding the async/await approach (which was avoided by the Virtual Threads proposal):

"Provide syntactic stackless coroutines (async/await) in the Java language. These are easier to implement than user-mode threads and would provide a unifying construct representing the context of a sequence of operations, but that construct would be new, separate from threads while being similar to them in many respect yet different in some nuanced ways, would still split the world of APIs between those designed for threads and those designed for async/await, and would require the new thread-like construct to be introduced into all aspects of the platform and its tooling, resulting in something that would take longer for the ecosystem to adopt while not being as elegant and harmonious with the platform as user-mode threads. Most languages that have chosen to adopt async/await have done so due to an inability to implement user-mode threads (Koltin), legacy semantic guarantees (JavaScript), or language-specific technical constraints (C++). These do not apply to Java."

I wonder if Rust should also be included in the final sentences.


It does no function coloring. Just block :). Virtual threads are preemptive not cooperative.


It doesn’t block, that’s the whole point. The runtime knows if a given method is blocking or not and under the hood even blocking IO calls are implemented with non-blocking IOs. So those can be preempted.


Yes I know. “Just block” refers to just waiting on virtual threads/futures via get or join. No fancy observables or callbacks etc.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: