4

The tutorials and documentation I've read all say that goroutines are "not quite threads" or "lightweight threads" but can usually be treated like they are their own separate thread.

So... What are they really?

Corey Ogburn
  • 24,072
  • 31
  • 113
  • 188
  • Read the implementation? – Simeon Visser Jan 05 '15 at 22:48
  • 1
    Where can I find the implementation on built-in keywords? – Corey Ogburn Jan 05 '15 at 22:51
  • 1
    http://dave.cheney.net/2014/06/07/five-things-that-make-go-fast can help. – VonC Jan 05 '15 at 23:00
  • I haven't looked but in Go's source of course - I was mainly saying that the only way to answer this definitively is to review the source and study it. – Simeon Visser Jan 05 '15 at 23:01
  • You could call them "user-mode threads" multiplexed onto OS threads by a user-mode scheduler. That is: when one goroutine starts waiting on a blocking operation (say, an HTTP call to a remote server), the Go runtime looks for something else that can run, and switches to it (even if the last time it ran, it ran on a different OS thread). – twotwotwo Jan 05 '15 at 23:07
  • Compared to the usual OS threads in Linux, Go threads have less switching overhead because you don't have to hop into kernel mode and back to user mode (and, more importantly, you don't have to run Linux's more complex fair scheduler), and rather than allocating lots of stack space, it initially allocates a few KB and it can grow as necessary later. I think (going a bit outside my firm knowledge here) people working on non-Go runtimes (Rust?) have talked about avoiding heavy allocation of physical RAM f/new threads using VM overcommit, though that has the caveat that it's an OS-wide setting. – twotwotwo Jan 05 '15 at 23:10
  • They are just fibers: https://en.wikipedia.org/wiki/Fiber_%28computer_science%29 – Nils Pipenbrinck Jan 05 '15 at 23:23
  • @NilsPipenbrinck Seems they might be more accurately interpreted as [coroutines](https://en.wikipedia.org/wiki/Fiber_%28computer_science%29#Fibers_and_coroutines) – Floegipoky Jan 05 '15 at 23:40
  • Essentially yes re: what Nils said; "green threads" are similar. (I think there are distinctions you could make, reading the definitions as WP phrases them, but all are, from the app perspective, processes implemented with the help of user-mode scheduling.) The performance benefit of goroutines/fibers/green threads is also similar to the boost some software gets from event-driven models (look at nginx/libuv/Node), though not all event driven tools show a thread-like abstraction to the user (e.g., Node makes you program with callbacks). – twotwotwo Jan 05 '15 at 23:40
  • There are fine distinctions--WP pages seem to say (correctly or not) that "fibers" doesn't refer to a language-level construct (and says the language-level version is called a coroutine) and that "pure fibers" and green threads "normally cannot" use multiple cores, unlike the [M:N (hybrid) threading](https://en.wikipedia.org/wiki/Thread_(computing)#Models) model goroutines follow. I suspect the highly specific baggage attached to "green thread," "fiber," and "coroutine" are part of why a new word was coined. (The other part being that the new word just sounded cool, haha.) – twotwotwo Jan 05 '15 at 23:50
  • To see a comparison betweeen goroutines and green threads, check http://programmers.stackexchange.com/questions/222642/are-go-langs-goroutine-pools-just-green-threads/222694#222694 – Didier Spezia Jan 06 '15 at 08:13

3 Answers3

17

A few things distinguish goroutines from typical OS threads:

  • There's user-mode scheduling. When a goroutine is blocked (waiting on the network, say), the Go runtime looks for another one that can run. This happens without having to enter and exit kernel mode and without the OS kernel's scheduler running.
  • There isn't only user-mode scheduling: to use multiple cores, Go will start multiple OS threads and run goroutines on all of them, potentially moving a goroutine between OS threads to keep everything busy. If you hear that goroutines are "multiplexed" onto OS threads, that's what it means.
  • They're meant to have low cost to start. Stacks start out small, only a few kilobytes and growing as needed, whether the OS is using virtual-memory overcommit or not.
  • They're tied in with the language; besides the go statement itself, there are channel types and operations and select statements for coordinating the goroutines.
  • They lack some OS threading features: currently, Go's scheduler doesn't guarantee fairness, and there's only very limited pre-emption (an empty for{} loop will never be switched away from).

They're closely related to lots of other terms:

  • fibers, a term used in connection with user-mode-scheduled threads
  • green threads, another term used to refer to user-mode-scheduled threads
  • coroutines, referring to routines that can yield control to each other at arbitrary points in their code
  • event-driven architectures, which might switch to other tasks while waiting on asynchronous events like network I/O, but may not present a thread-like interface (they might use callback functions instead, for example)
  • M:N hybrid threading, which involves both kernel- and user-mode threads, and can involve migration of user-mode threads across OS threads.
twotwotwo
  • 28,310
  • 8
  • 69
  • 56
1

When having two CPUs, goroutine(s) runs as real threads. When having single CPU, the goroutine(s) runs as co-routine of single thread that running with switching their contexts. goroutine doesn't stick the fixed thread. So it doesn't identifier like thread-id. If you want to stick goroutine as OS thread, you need to use runtime.LockOSThread().

mattn
  • 7,571
  • 30
  • 54
0

This Morsing's blog post about the Go scheduler is nice because it has pictures with triangles, squares and circles.

From the scheduler's point of view :

The goroutine includes the stack, the instruction pointer and other information important for scheduling.

Deleplace
  • 6,812
  • 5
  • 28
  • 41