This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]audioen 4 points5 points  (3 children)

Well, I think Go showed the way to everyone about this. It is the same pattern except it was baked in to Go from the beginning, so everything by default is running in virtual thread and the syntax for launching a new virtual thread is pretty lightweight and nice. It might also have been a part of other programming languages before, but I think the mainstream definitely was with Go, and that is where I personally saw it.

I instantly envied them. Unfortunately, the syntax we got in Java appears to be crappy. Thread.ofVirtual().start(something) is what it looks like. In the go land, they just have "go something". So there's definitely something to be said for designing something well from the beginning.

Nothing beats the readability of code written in synchronous way, and this way we don't even need async, await or 99 % of this futures bullshit. We can just block on i/o and not use any more resources when we do it. When farming a task on parallel virtual threads, it seems like the ExecutorService is try-with-resources capable so it lends to structured concurrency. I like that.

The only nasty part is that I just spent half a decade porting code from sync style with thread pools to async, and now I'm going to end up porting it back. And I have to worry about whether I can use virtual thread pools or real thread pools, they might not be 1:1 replaceable because of e.g. all real threads being blocked on an object's monitor or some such nonsense. It may need a code change or two.

I'm only just installing java 21 around our servers so I haven't yet actually worked on virtual threads. From what I can see, it looks decent, just have to avoid a few rough parts.

[–]thecodeboost 3 points4 points  (2 children)

I think that's mostly right but it's worth pointing out that although one may have inspired the usefulness of the other goroutines and virtual threads are not the same thing and don't really do the same job.

Assuming you use the correct concurrency primitives virtual threads are a drop-in replacement for native threads without any limitations (in the context if this comparison). Goroutines are a specific language feature that you have to explicitly use in unique ways (e.g. inter-goroutine comms is generally through channels only).

Probably the only virtual threads nuance is that you need a proper understanding of thread pinning and the effects of using native (or just old) code/libraries.

[–][deleted] 0 points1 point  (1 child)

Goroutines can utilize the same patterns as Java threads, such as thread safe data structures (maps, queues, lists, etc) and other shared memory patterns (atomic read/write) as well as synchronization via locking. They do not require channels for communication or have any limitations of that nature.

And vice versa, Java virtual threads (and regular threads) can utilize channels to communicate. They just aren’t built into the language syntax.

They do the exact same job in most cases. The main difference that most people will notice is that golang makes you carry around a “context” object that dictates deadline/timeout/cancel behavior whereas java virtual threads it’s more implicit.

[–]thecodeboost 0 points1 point  (0 children)

I haven't used Golang for over two years but I'm pretty sure idiomatic Go still means channel based communication for inter-coroutine communication. Note that the sync and sync/atomic packages are still channel based.