In the Google I/O 2012 presentation Go Concurrency Patterns, Rob Pike mentions that several goroutines can live in one thread. Does this imply that they are implemented as coroutines? If not, how they are implemented? Links to source code would be welcome.
Golang provides goroutines to support concurrency in Go. A goroutine is a function that executes simultaneously with other goroutines in a program and are lightweight threads managed by Go. A goroutine takes about 2kB of stack space to initialize.
Goroutine is a lightweight thread in Golang. All programs executed by Golang run on the Goroutine. That is, the main function is also executed on the Goroutine. In other words, every program in Golang must have a least one Goroutine.
Goroutines are functions or methods that run concurrently with other functions or methods. Goroutines can be thought of as lightweight threads. The cost of creating a Goroutine is tiny when compared to a thread. Hence it's common for Go applications to have thousands of Goroutines running concurrently.
Go is different, and a goroutine is not the same as a thread. Threads are much more expensive to create, use more memory and switching between threads takes longer. Goroutines are an abstraction over threads and a single Operating System thread can run many goroutines.
IMO, a coroutine implies supporting of explicit means for transferring control to another coroutine. That is, the programmer programs a coroutine in a way when they decide when a coroutine should suspend execution and pass its control to another coroutine (either by calling it or by returning/exiting (usually called yielding)).
Go's "goroutines" are another thing: they implicitly surrender control at certain indeterminate points1 which happen when the goroutine is about to sleep on some (external) resource like I/O completion, channel send etc. This approach combined with sharing state via channels enables the programmer to write the program logic as a set of sequential light-weight processes which removes the spaghetti code problem common to both coroutine- and event-based approaches.
Regarding the implementation, I think they're quite similar to the (unfortunately not too well-known) "State Threads" library, just quite lower-level (as Go doesn't rely on libc
or things like this and talks directly to the OS kernel) — you could read the introductory paper for the ST library where the concept is quite well explained.
1 In fact, these points are less determinate than those of coroutines but more determinate than with true OS threads under preemptive multitasking, where each thread might be suspended by the kernel at any given point in time and in the flow of the thread's control.
Update on 2021-05-28: actually, since Go 1.14, goroutines are scheduled (almost) preemptively. It should be noted though, that it's still not that hard-core preemption a typical kernel does to the threads it manages but it's quite closer than before; at least it's now impossible for a goroutine to become non-preemptible once it enters a busy loop.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With