What Loom and Go do is to schedule green threads on a bunch of system threads and spawn more system threads when they get blocked doing synchronous system calls.
What Loom and Go do is to schedule green threads on a bunch of system threads and spawn more system threads when they get blocked doing synchronous system calls.
(And if you want to be pedantic, IIRC the green threads were originally mapped to the Java process, not a thread, because threads were either unavailable or immature in Linux when Java 1 came out; I can’t remember which)
The green threads on the JVM were not the same kind as green threads in Go (and Loom), they would block on IO. Can't speak for Loom, but Go automagically reschedules your green thread when it blocks which allows other threads to run while waiting.
The point is they weren't rescheduled when they would block in the JVM, every process has a main thread.
But I find the cycle - what I called the hype cycle - from internal scheduling to external scheduling and back again, interesting, and I wonder what, if anything, we as an industry can learn from this?
ISTM that Java 1.2 could have improved on green threads instead of moving to os threads. So, is there something we can learn from these two transitions that will help us all make better decisions in the future? The use of OS threads and all the complexity that this has caused has cost the industry hundreds of thousands of hours of developer time. If we can learn some lessons from this then isn’t that a good thing?
1. Threading got much faster and lightweight. This is what Java was initially trying to work around, until it didn't have to any more.
2. The problem moved to handling as many sockets concurrently as possible. Even lightweight system threads are too heavy for scaling linearly with the number of connections (too much context-switching overhead, too much space for stack, etc.)
Green-threading has become a good idea again because we now have a kernel API that is used to multiplex a lot (but not all) I/O systemcalls.
Today Go runtime uses epoll/kqueue to read from a big bunch of sockets, whenever something new happens to any of them. This takes one system thread only.
The API model of epoll/kqueue implies some way to handle concurrency in your user code: this can either be callbacks (or async/await syntactic sugar) or green threads and CSP (channels and so on.) This is why green threading is having a comeback.
(Sorry for implying you did not read the article!)
> Green-threading has become a good idea again because we now have a kernel API that is used to multiplex a lot (but not all) I/O systemcalls.
OK, that makes a lot of sense. I had to read up about how epoll is different from select/poll (that's how long it's been since I worked in C :). Clearly epoll was needed to make green threads efficient, but from what I can see, by the time epoll and friends were widespread, the pthread model was entrenched in Java.