In Golang Concurrency Part I, I said Goroutines are not threads. In this post I will explain the same.
Size
OS threads are basically fixed size stack, preferably 2 MB. It’s a huge space e.g. invoking 1024 threads will result in 2 GB space occupancy.
A Goroutine starts life with a small stack, typically 2 KB. Because some go routines are too small for a 2 MB stack and stack of Goroutine is growable.
The size limit for a Goroutine stack may be as much as 1GB, so thread is limited for recursive operation because recursive stack greater then 2 MB will cause, stack overflow. Go o the other hand can grow it’s stack to 1 GB, WOW, now huge recursion is possible in Go.
Scheduling
OS threads are scheduled by kernel. Hardware timer dependency.
Go run-time has its own scheduler. No hardware timer dependency. It’s a m:n scheduler. Means, m (Goroutines) => n ( Threads).
Identity
Goroutines has no identity, for some it must be an issue, but I can easily live with that. Go has this implemented because Goroutines has no TLS (Thread local storage).
Goroutines are part of making concurrency easy to use. The idea, which has been around for a while, is to multiplex independently executing functions—coroutines—onto a set of threads. When a coroutine blocks, such as by calling a blocking system call, the run-time automatically moves other coroutines on the same operating system thread to a different, runnable thread so they won't be blocked. The programmer sees none of this, which is the point. The result, which we call goroutines, can be very cheap: they have little overhead beyond the memory for the stack, which is just a few kilobytes.
To make the stacks small, Go's run-time uses resizable, bounded stacks. A newly minted goroutine is given a few kilobytes, which is almost always enough. When it isn't, the run-time grows (and shrinks) the memory for storing the stack automatically, allowing many goroutines to live in a modest amount of memory. The CPU overhead averages about three cheap instructions per function call. It is practical to create hundreds of thousands of goroutines in the same address space. If goroutines were just threads, system resources would run out at a much smaller number.
In Golang Concurrency Part I, I said Goroutines are not threads. In this post I will explain the same.
Size
OS threads are basically fixed size stack, preferably 2 MB. It’s a huge space e.g. invoking 1024 threads will result in 2 GB space occupancy.
A Goroutine starts life with a small stack, typically 2 KB. Because some go routines are too small for a 2 MB stack and stack of Goroutine is growable.
The size limit for a Goroutine stack may be as much as 1GB, so thread is limited for recursive operation because recursive stack greater then 2 MB will cause, stack overflow. Go o the other hand can grow it’s stack to 1 GB, WOW, now huge recursion is possible in Go.
Scheduling
OS threads are scheduled by kernel. Hardware timer dependency.
Go run-time has its own scheduler. No hardware timer dependency. It’s a m:n scheduler. Means, m (Goroutines) => n ( Threads).
Identity
Goroutines has no identity, for some it must be an issue, but I can easily live with that. Go has this implemented because Goroutines has no TLS (Thread local storage).
Goroutines are part of making concurrency easy to use. The idea, which has been around for a while, is to multiplex independently executing functions—coroutines—onto a set of threads. When a coroutine blocks, such as by calling a blocking system call, the run-time automatically moves other coroutines on the same operating system thread to a different, runnable thread so they won't be blocked. The programmer sees none of this, which is the point. The result, which we call goroutines, can be very cheap: they have little overhead beyond the memory for the stack, which is just a few kilobytes.
To make the stacks small, Go's run-time uses resizable, bounded stacks. A newly minted goroutine is given a few kilobytes, which is almost always enough. When it isn't, the run-time grows (and shrinks) the memory for storing the stack automatically, allowing many goroutines to live in a modest amount of memory. The CPU overhead averages about three cheap instructions per function call. It is practical to create hundreds of thousands of goroutines in the same address space. If goroutines were just threads, system resources would run out at a much smaller number.