Skip to content

What is a goroutine, if not a thread?

Level: 201 · anyone moving between Go and a language with real threads

Stub — a question and its expected answers, not yet a lesson. No program behind this page has been written or run, so nothing on it has been through the check that backs every finished page. The table is what the finished lesson is expected to find, and every cell is unverified until a program prints it. (Not machine-checked here.)

One line: A goroutine, a Java virtual thread and a Rust async task are all user-space units of execution that a runtime multiplexes onto a few operating-system threads — cheap to start, cheap to block, and invisible to the operating system — and the price is that a call which blocks the underlying thread without telling the runtime stalls every other unit sharing it.

The question

go f() starts something that looks like a thread and is not one. Neither is Thread.ofVirtual().start(...) nor tokio::spawn. What do they share, where do they run, and what do they cost? The page starts all three, then asks the question that separates them from threads: what happens when one of them makes a blocking system call?

What each language is expected to say

Expected answer, to be verified by the program
Rust no green threads since 2014; async tasks on a runtime are the equivalent, and a blocking call inside one stalls its worker thread
Go goroutines on GOMAXPROCS threads; the runtime moves a blocked goroutine off its thread, so a blocking syscall costs a thread, not the program
C none: a thread is a thread, and any lighter unit is a library (ucontext, or a coroutine library)
C++ none in std; C++20 coroutines are a building block without a scheduler
Java virtual threads (Java 21) on a ForkJoinPool of carriers; a synchronized block used to pin the carrier, fixed in Java 24
Python asyncio tasks on one thread; threading threads are real ones

What the programs have to show

  • ten thousand units started and joined, printing the count and the number of OS threads the process had at the peak
  • one unit doing a blocking read on a pipe that is never written, while the others keep printing — or stop
  • a Real runs fence with start time and memory for a thousand of each

See also